1

If I have:

int a = 123;
int b = 456;

How do I get?:

double c = 123.456;
Martin Zabel
  • 3,589
  • 3
  • 19
  • 34
Ignacio Garat
  • 1,536
  • 6
  • 24
  • 48
  • 4
    What did you try? Would `int a = 1; int b = 23456;` result in `1.23456`? What are you actually trying to do/what are you using that for? – Thomas Jun 03 '16 at 14:34
  • 1
    Have you tried multiplying the second number by something like `.001` and then adding that to the first one? – Cache Staheli Jun 03 '16 at 14:35
  • Could be a Money class with whole and fractional parts. You'd need a general way to get the size of the divisor for the fractional part. – duffymo Jun 03 '16 at 14:37
  • @Thomas I'm joining together two ints one from a MeterNumberPicker, an the other one for the CentimeterNumberPicker – Ignacio Garat Jun 03 '16 at 14:39
  • Related in C# http://stackoverflow.com/q/18432640/1743880 – Tunaki Jun 03 '16 at 14:42
  • I would say this is a bad design, because it has no insight into units. If you encapsulate this into a Length object that has scalar value and units encapsulated together it'd be far better. Martin Fowler won't yell at you. You can also encapsulate unit conversions (e.g. meters to furlongs, etc.) http://martinfowler.com/eaaDev/quantity.html – duffymo Jun 03 '16 at 17:42

6 Answers6

15

How about this:

int a = 123; int b = 456;
double c = Double.parseDouble(a + "." + b);
Jorn Vernee
  • 31,735
  • 4
  • 76
  • 93
  • 1
    The easiest way, +1 – Dmitry Bychenko Jun 03 '16 at 14:52
  • 1
    Since he's using a number picker he might actually have strings in the first place which are parsed into ints. If that's the case one could just skip that integer parsing part - in any case that's probably still the simplest approach. Thus +1 – Thomas Jun 03 '16 at 14:56
8

Mathematical solution

  int a = 123; 
  int b = 456;

  double c = a + (b == 0 ? 0 : b / Math.pow(10, 1 + (int) Math.log10(b)));

explanation:

   1 + (int) Math.log10(b)     // number of digits (3 in case of 123)
   Math.pow(10, 1 + ... )      // 10...0 - 1 with required number of zeroes
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • 1
    @Tom: thank you! Of course it should be `c = a + ...` – Dmitry Bychenko Jun 03 '16 at 14:43
  • I would also add a note about the fact that it is not possible to achieve perfect results, even for some [simple values](http://stackoverflow.com/questions/5257166/java-floats-and-doubles-how-to-avoid-that-0-0-0-1-0-1-0-9000001). Other problematic cases are: signed int, very big int. – Giulio Paci Jun 03 '16 at 14:54
  • Although this approach might suffer from some precision issues which the string parsing approach does not (at least not to the same extent) and is more complex to read it is the faster approach and thus might be preferable if performance is an issue. – Thomas Jun 03 '16 at 15:19
  • An even faster approach might be to just employ a loop and divide `b` by 10 until it is smaller than 1. – Thomas Jun 03 '16 at 15:30
  • @GiulioPaci even the string parsing approach would suffer from those cases (try parsing `"1.-2"`). Negative numbers are always a problem and should not be allowed here and precision problems with very large numbers could be alleviated by using `BigDecimal` (although you'd then not be able to use `Math.log10()` etc.). – Thomas Jun 03 '16 at 15:33
  • @Thomas: I personally do not like the string parsing approach. I originally wrote an answer that was very close to this one, but deleted because this one was more complete. I suggested to add this notice to this answer because it is my favourite, but indeed it should be added to any valid answer to this question. – Giulio Paci Jun 03 '16 at 17:09
2

Create strings out of each integer, then concatenate the strings together, inserting a "." between the two. Then convert the resulting string to a double.

Subhrajyoti Majumder
  • 40,646
  • 13
  • 77
  • 103
FredK
  • 4,094
  • 1
  • 9
  • 11
2

If you want to take a purely computational approach, as opposed to one involving conversion back and forth between string and numeric form, then you could do this:

double concatToDouble(int integer, int fraction) {
    if (fraction < 0) {
        throw new NumberFormatException("The fractional part must not be negative");
    } else if (fraction == 0) {
        return integer;
    } else {
        int numFractionDigits = (int) Math.log10(fraction) + 1;
        int scaleFactor = (int) (Math.pow(10, numFractionDigits) + 0.1);

        return (double) ((long) integer * scaleFactor
                + (long) Math.signum(integer) * fraction)
                / scaleFactor;
    }
}

It's a little longer to express, but it will perform better because it involves a lot less work than the conversions to and from string format.

Computational notes:

  • Scaling up the integer part, performing integer addition, and then scaling down the sum will get you the closest possible result to the double you want, but
  • in many cases, double has no exact representation for the decimal number you want to form.
  • I have chosen types carefully and intentionally. In particular, I convert the value of integer to type long before computing the scaled value, so as to avoid overflow.
  • Math.signum() returns 1.0 for arguments greater than 0, and -1.0 for arguments less than zero. This allows the method to handle negative values of integer gracefully.
  • I add 0.1 to the result of Math.pow() before truncating the result to an integer in case the result of pow(), which isn't necessarily exact, is slightly smaller than the exact result.

Do note, however, that the problem itself seems not to account for the (infinitely many) insignificant leading zeroes that notionally precede the significant digits of the fraction part. That is, without a third parameter indicating the scale of the fraction part, there is no way to get a result of 123.0456, 123.00456, etc..

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Nice because it checks for negative inputs. Not nice that it doesn't compile, because there's missing `;` and a `Uncompilable source code - incompatible types: possible lossy conversion from double to int` compiler error. The edit you rejected as "superfluous" actually made it compile and work. What's "superfluous" about making code actually compile? Code isn't required to compile anymore? – Arjan Jun 03 '16 at 15:21
  • @Arjan, your edit would have been much better in the form of the comment you afterward made. Edits of answers are rarely well received. In any case, I was in the process of a series of edits myself. I think you will find that the issues you identified are now resolved, and then some. – John Bollinger Jun 03 '16 at 15:37
  • +1 for thinking of precision issues (e.g. the epsilon part), negative integer parts and leading zeros in the fraction part. One question though: doesn't `(integer * scale + fraction) / scale` (I intentionally left out the signum part) have more precision issues than `integer + (fraction / scale)`? AFAIK double precision should be highest for values in range [0,1]. – Thomas Jun 03 '16 at 15:58
  • @Thomas, all the arithmetic in the final computation is *integer* arithmetic, except the division at the end. Integer arithmetic is exact, which is the reason for preferring it here. – John Bollinger Jun 03 '16 at 16:17
  • Thank you for explaining about the edit, and yes your edits turned it into a great answer and explanation :) I'm a bit skeptical about the "better performance". I ran some [tests](http://pastebin.com/hARxn1bn) to time the string and math solutions for various ranges of integers and can't say the math solution is [faster](http://postimg.org/image/xt742gefv/). Perhaps Math.pow isn't cheap? Either way, +1 for a great answer :) – Arjan Jun 03 '16 at 19:16
  • Hmm, yes `integer + (fraction / scale)` would have one more double operation - the `add`. However, converting large long values to double will eventually lose some precision too so it's probably not that much of a difference. I conducted some tests which indicate that you only get precision differences for very large integer and fraction parts and in those cases which approach held the better precision depended on the initial values. – Thomas Jun 06 '16 at 07:42
0

If the size of b is not aleatory, simply initialize a new wrapper:

new Double(a + ((double)b / 1000))

Note that I'm casting b to double explicitly here, in order to obtain a double value of b / 1000 instead of an integer value.

Mena
  • 47,782
  • 11
  • 87
  • 106
0

If size of the ints shouldn't matter,

public class TestStackOverflowQuestion {

    public static void main(String[] args) {
        int a = 123;
        int b = 456;
        double c = a + Double.parseDouble("." + b);
        System.out.println(c);
    }
}
Arjan
  • 823
  • 1
  • 7
  • 18
  • Why do you parse only have of the double, instead of creating the complete number in a String and parse that? – Tom Jun 03 '16 at 14:40
  • 1
    @Tom because it's not necessary to create the complete number in a String and parse that... so why would I? – Arjan Jun 03 '16 at 14:44