0

I have a line of code that adds together a few doubles and it give a result of infinity, while the double are all just small but long decimals

a = -1.536709757154733E308
b =  2.102331119338414E156
c =  0.2

d = a - b + (a * c)
d = -1.536709757154733E308 - 2.102331119338414E156 + (-1.536709757154733E308 * 0.2)
d = -infinity

Does anyone know why this is happening? Any help would be much appreciated

PS it is not feasible to use Big Decimals in this code and due to the random 'a' and 'b' change on each run

Ryaller
  • 77
  • 3
  • 12

3 Answers3

1

Overflow is occurring. The magnitude of the result of the expression a - b + (a * c) is greater than the largest possible double, Double.MAX_VALUE, or 1.7976931348623157E308. When this occurs, the result is an infinity. Because a was negative, this results in -Infinity.

You can see this if you decrease the exponents of a and b by 1 to see what the result would be:

-1.8440517085856795E307

Increasing the exponent by 1 again in the result would yield a magnitude larger than the maximum possible magnitude.

You can still use BigDecimals.

BigDecimal a =  new BigDecimal(-1.536709757154733E308);
BigDecimal b =  new BigDecimal(2.102331119338414E156);
BigDecimal c =  new BigDecimal(0.2);

System.out.println(a.add(b).add(a.multiply(c)));
rgettman
  • 176,041
  • 30
  • 275
  • 357
0

That decimal point is deceiving you. To see how large that double value actually is, use the NumberFormat as

double d = 2.102331119338414E156;
System.out.println(NumberFormat.getNumberInstance().format(d));

Output :

2,102,331,119,338,414,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000

Hence, switching to a BigDecimal should help. If you're generating the a and b values randomly, take a look at Generating random BigDecimal value from given range.

Community
  • 1
  • 1
Ravi K Thapliyal
  • 51,095
  • 9
  • 76
  • 89
0

So, with the scientific notation and large numbers represented out of the way, let's look at a simplified form.

a = -1.5E308    // round down*
b =  2.1E156
c =  0.2

d = a - b + (a * c)
d = -1.5E308 - 2.1E156 + (-1.5E308 * 0.2)
d = -1.5E308 - {insignificant*} + (-0.3E308)
d = -1.8E308   // under normal math ..

.. BUT, 64-bit IEEE 754 Double's - which is the format that double is stored in - have a range of ~[-1.79E308, 1.79E308] as only so much information can be stored in 64 bits.

The result of -1.8E308 is outside of this range. Hence it is represented as (negative) Infinity.


* Note the initial round down and throwing away the insignificant value - this the result is guaranteed to be < -1.8E308, although feel free to work it out to more precision. The point is this is outside the representable range of a double.

Using a BigDecimal works because (and it doesn't matter if the input is "random") because it doesn't have this range limit.

user2864740
  • 60,010
  • 15
  • 145
  • 220