Java - 当它们只是小而长的小数时,多个双精度相加无穷大

时间:2015-03-06 18:42:49

标签: java

我有一行代码添加了几个双精度数,它给出了无穷大的结果,而双精度数只是小而长的小数

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

有谁知道为什么会这样?任何帮助将不胜感激

PS在此代码中使用大十进制是不可行的,并且由于随机的' a'和' b'每次运行都要改变

3 个答案:

答案 0 :(得分:1)

正在发生溢出。表达式a - b + (a * c)的结果大小大于最大可能doubleDouble.MAX_VALUE1.7976931348623157E308。发生这种情况时,结果是无穷大。由于a为否定,因此会产生-Infinity

如果您将ab的指数减少1以查看结果,可以看到这一点:

-1.8440517085856795E307

在结果中再次增加指数1会产生比最大可能幅度大的数量。

您仍然可以使用BigDecimal s。

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)));

答案 1 :(得分:0)

小数点欺骗了你。要查看double值实际有多大,请使用NumberFormat作为

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

输出:

  

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

因此,切换到BigDecimal应该会有所帮助。如果您随机生成ab值,请查看Generating random BigDecimal value from given range

答案 2 :(得分:0)

所以,在scientific notation and large numbers represented开始的情况下,让我们看一下简化的表格。

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 ..

..但是64-bit IEEE 754 Double's - 这是double存储的格式 - 范围为〜[-1.79E308, 1.79E308],因为只有这么多信息可以以64位存储。

-1.8E308的结果是在此范围之外。因此它表示为(negative) Infinity


* 注意初始向下舍入并丢弃无关紧要的值 - 结果保证<&lt; -1.8E308,虽然随意使用它可以更精确。关键是 double的可表示范围。

使用BigDecimal是有效的,因为它没有这个范围限制,因此输入是“随机”并不重要。