Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b0adca9

Browse files
Merge pull request giantray#90 from RWBUPT/patch-2
Create why-does-math.round-(0.49999999999999994)-return-1.md
2 parents 2630b3e + 9ceec4f commit b0adca9

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
##为什么Math.round(0.49999999999999994)返回1?
2+
3+
###问题描述:
4+
5+
在下面的程序中你可以看到每个稍微比.5小的值都被向下舍入了,除了`0.5`那个。
6+
7+
```
8+
for (int i = 10; i >= 0; i--) {
9+
long l = Double.doubleToLongBits(i + 0.5);
10+
double x;
11+
do {
12+
x = Double.longBitsToDouble(l);
13+
System.out.println(x + " rounded is " + Math.round(x));
14+
l--;
15+
} while (Math.round(x) > i);
16+
}
17+
```
18+
输出
19+
```
20+
10.5 rounded is 11
21+
10.499999999999998 rounded is 10
22+
9.5 rounded is 10
23+
9.499999999999998 rounded is 9
24+
8.5 rounded is 9
25+
8.499999999999998 rounded is 8
26+
7.5 rounded is 8
27+
7.499999999999999 rounded is 7
28+
6.5 rounded is 7
29+
6.499999999999999 rounded is 6
30+
5.5 rounded is 6
31+
5.499999999999999 rounded is 5
32+
4.5 rounded is 5
33+
4.499999999999999 rounded is 4
34+
3.5 rounded is 4
35+
3.4999999999999996 rounded is 3
36+
2.5 rounded is 3
37+
2.4999999999999996 rounded is 2
38+
1.5 rounded is 2
39+
1.4999999999999998 rounded is 1
40+
0.5 rounded is 1
41+
0.49999999999999994 rounded is 1
42+
0.4999999999999999 rounded is 0
43+
```
44+
我使用 Java 6 update 31。
45+
46+
###回答:
47+
48+
**总结**
49+
50+
在Java 6中(而且很可能更早),`round x``floor(x+0.5)`的方式执行[1]。这是一个规则上的bug,它恰好会导致这样一种不合道理的情况[2]。Java 7不再授权这种分离的执行方式[3]
51+
52+
**问题**
53+
54+
0.5+0.49999999999999994在双精度数中正好表示1:
55+
```
56+
static void print(double d) {
57+
System.out.printf("%016x\n", Double.doubleToLongBits(d));
58+
}
59+
60+
public static void main(String args[]) {
61+
double a = 0.5;
62+
double b = 0.49999999999999994;
63+
64+
print(a); // 3fe0000000000000
65+
print(b); // 3fdfffffffffffff
66+
print(a+b); // 3ff0000000000000
67+
print(1.0); // 3ff0000000000000
68+
}
69+
```
70+
这是因为0.49999999999999994有一个比0.5小的指数,所以它们相加时,它的尾数被移位了,ULP(ULP表示现有数值最后一位代表的最小数值单位,小于ULP的数值将无法累加到现有数值)变的更大。
71+
72+
**解决方法**
73+
74+
从Java 7开始,OpenJDK(如下例)这样执行它(round函数)[4]
75+
```
76+
public static long round(double a) {
77+
if (a != 0x1.fffffffffffffp-2) // greatest double value less than 0.5
78+
return (long)floor(a + 0.5d);
79+
else
80+
return 0;
81+
}
82+
```
83+
[1] http://docs.oracle.com/javase/6/docs/api/java/lang/Math.html#round%28double%29
84+
85+
[2] http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6430675 (credits to @SimonNickerson for finding this)
86+
87+
[3] http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html#round%28double%29
88+
89+
[4] http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/lang/Math.java#Math.round%28double%29
90+
91+
92+
[stackoverflow链接:Why does Math.round(0.49999999999999994) return 1?](http://stackoverflow.com/questions/9902968/why-does-math-round0-49999999999999994-return-1)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /