我有一行代码,它把几个双精度加在一起,得到的结果是无穷大,而双精度都只是小而长的小数
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"one_answers"b"变化
发生溢出。表达式a - b + (a * c)
的结果的大小大于最大可能的double
、Double.MAX_VALUE
或1.7976931348623157E308
。当这种情况发生时,结果是无穷大。因为a
是阴性的,这导致了-Infinity
。
如果你把a
和b
的指数减少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)));
小数点在欺骗你。要查看double
的实际值有多大,请使用NumberFormat
作为
double d = 2.102331119338414E156;
System.out.println(NumberFormat.getNumberInstance().format(d));
输出:
21023311193384140000000000000000000000000000000000000000000000000000000000000000000
因此,切换到BigDecimal
应该会有所帮助。如果您随机生成a
和b
值,请查看从给定范围生成随机BigDecimal值。
因此,通过科学记数法和大数字的表示,让我们来看一个简化的形式。
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位IEEE 754 Double's(即double
的存储格式)的范围为~[-1.79E308, 1.79E308]
,因为64位中只能存储这么多信息。
CCD_ 19的结果在该范围的之外。因此,它被表示为(负)无穷大。
*注意最初的四舍五入并丢弃不重要的值-这一结果保证为<-1.8E308,尽管可以更精确地计算。重点是这是在double
的可表示范围之外的。
使用BigDecimal之所以有效,是因为(输入是否为"随机"并不重要),因为它没有这个范围限制。