双精度的输出是怎么回事?



当我把双打加在一起时,我得到了奇怪的输出。有人能告诉我为什么每次加0.1都会重复小数吗?

我已经算出了把这些数字加在一起的公式,我自己在纸上做了这个,直到3.3…

所有数字的总和(减少十分之一)从3.3到1等于51.6

3.3
3.2
3.1+
3.0

1.0
_
51.6

有一种更简单的方法可以使用两个公式来计算:

递增数的线性公式:Y=0.1X+1
递增数的和公式:[X*(Y+1)]/2=总数

首先使用任意数字(在本例中为100)求解Y

11=0.1(100)+1


然后使用X和Y 求解总数

[100*(11+1)]/2=600

我相信以下代码的输出应该是600。毫无疑问,它不应该有一个重复的小数。我在这里做错了什么?我一定错过了什么。

public static void main(String[] args) {
int days = 100;
double inc = 0.1;
double init = 1;
double total = 0;
for (int i = 1; i <= days; i++) {
if (i == 1) {
total = total + init;
} else {
init = init + inc;
total = total + init;
}
}
System.out.println("Total: " + total);
System.out.println("Daily: " + init);
}

Double没有无限精度(BigDecimal也没有,但BigDecimals有足够的精度用于此实现)。

试试这个,

public static void main(String[] args) {
int days = 100;
java.math.BigDecimal init = java.math.BigDecimal.ONE;
java.math.BigDecimal total = java.math.BigDecimal.ZERO;
java.math.BigDecimal oneTenth = new java.math.BigDecimal(
"0.1");
for (int i = 1; i <= days; i++) {
if (i != 1) {
init = init.add(oneTenth);
}
total = total.add(init);
}
System.out.println("Total: " + total);
System.out.println("Daily: " + init);
}

哪个输出

Total: 595.0
Daily: 10.9

请阅读Don Roby发布的链接。从本质上讲,双精度不是表示分数的好方法。像0.1这样的数字在二进制浮点表示法中没有精确的表示法,因为浮点数被写成"某物的二次方"。对于0.1,你不能完全解决这个问题。因此,你真的得到了一个稍微小一点的数字——实际上是

0.0999999999999998

而这个缺失的数量足以扰乱数学…

请参阅Jon Skeet关于此主题的精彩回答:https://stackoverflow.com/a/1089026/1967396

公式应该是

0.1 * (100 * (100 + 1) / 2)

除了你从10*0.1开始,所以公式更复杂。

在任何情况下,双精度都不准确,尤其是对于0.1这样的数字,所以你应该会得到舍入误差。

你可以通过使用数字来解决这个问题,这些数字可以像1一样精确地表示,而不是0.1(或四舍五入结果)

public static void main(String... ignored) {
int days = 100;
double inc = 1;
double init = 10;
double total = 0;
for (int i = 1; i <= days; i++) {
if (i == 1) {
total = total + init;
} else {
init = init + inc;
total = total + init;
}
}
total /= 10;
init /= 10;
System.out.println("Total: " + total);
System.out.println("Daily: " + init);
}

或者对结果进行四舍五入。

public static void main(String... ignored) {
int days = 100;
double inc = 0.1;
double init = 1;
double total = 0;
for (int i = 1; i <= days; i++) {
if (i == 1) {
total = total + init;
} else {
init = init + inc;
total = total + init;
}
}
System.out.printf("Total: %.1f%n", total);
System.out.printf("Daily: %.1f%n", init);
}

两者都打印

Total: 595.0
Daily: 10.9

最新更新