自增双精度值的最后一位



我有一个双变量,像80.146666666668,然后我使用地板函数截断它直到8位数,像80.14666666。现在我想增加这个值,得到答案为80.14666667

您可能没有意识到double的真实性质。它们没有"数字";它们是一种紧凑的有理数二进制编码。因此,您会发现很难通过编程确定double的"最后一位数字"是什么。

如果您的具体需要只是四舍五入,那么使用round函数而不是truncate;否则可以考虑使用BigDecimal,它真正代表一个十进制数字。

一个快速的方法是:

double myNumber = 80.14666666;
myNumber += (1 / 10^8); // = 80.14666667

这是你想要的吗?

双精度类型实际上并不包含您想象的确切值。这是因为底层字段被保存为二进制数,由于1/5的因素,不能包含十分位数。

你可以使用new BigDecimal("80.14666666")并增加new BigDecimal("0.00000001")。

注意,我传递了一个字符串来初始化这个对象。如果你传递一个双精度类型,BigDecimal将根据双精度类型的值被初始化,正如前面提到的,它不包含你想象的确切值。

只需在数字上加上0.00000001。

但是,浮点值不太适合这样计数。每次增加它时,都将增加一个差异,因为这样的数字只能近似地表示为浮点数。

如果要增加数字,请使用整数代替。将该数字乘以100000000并将其转换为整数,从而得到8014666666。现在您可以在不引入任何错误的情况下将整数增加1。保留整数进行递增,并根据需要通过除以100000000将其转换为浮点格式。当然,浮点值在精度上仍有其局限性,但每个浮点值都是由其对应的整数转换而来的,并且整数值没有任何精度问题,因此每次递增时不会累积错误。