如何按最小增量更改 double
是不是有什么东西坏了或者我不明白发生了什么?
static String getRealBinary(double val) {
long tmp = Double.doubleToLongBits(val);
StringBuilder sb = new StringBuilder();
for (long n = 64; --n > 0; tmp >>= 1)
if ((tmp & 1) == 0)
sb.insert(0, ('0'));
else
sb.insert(0, ('1'));
sb.insert(0, '[').insert(2, "] [").insert(16, "] [").append(']');
return sb.toString();
}
public static void main(String[] argv) {
for (int j = 3; --j >= 0;) {
double d = j;
for (int i = 3; --i >= 0;) {
d += Double.MIN_VALUE;
System.out.println(d +getRealBinary(d));
}
}
}
带输出:
2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000]
2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000]
2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000]
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000]
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000]
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000]
4.9E-324[0] [00000000000] [000000000000000000000000000000000000000000000000001]
1.0E-323[0] [00000000000] [000000000000000000000000000000000000000000000000010]
1.5E-323[0] [00000000000] [000000000000000000000000000000000000000000000000011]
Is something broken or I fail to understand what is happening?
static String getRealBinary(double val) {
long tmp = Double.doubleToLongBits(val);
StringBuilder sb = new StringBuilder();
for (long n = 64; --n > 0; tmp >>= 1)
if ((tmp & 1) == 0)
sb.insert(0, ('0'));
else
sb.insert(0, ('1'));
sb.insert(0, '[').insert(2, "] [").insert(16, "] [").append(']');
return sb.toString();
}
public static void main(String[] argv) {
for (int j = 3; --j >= 0;) {
double d = j;
for (int i = 3; --i >= 0;) {
d += Double.MIN_VALUE;
System.out.println(d +getRealBinary(d));
}
}
}
With output:
2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000]
2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000]
2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000]
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000]
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000]
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000]
4.9E-324[0] [00000000000] [000000000000000000000000000000000000000000000000001]
1.0E-323[0] [00000000000] [000000000000000000000000000000000000000000000000010]
1.5E-323[0] [00000000000] [000000000000000000000000000000000000000000000000011]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
浮点数不像整数类型那样均匀地分布在数轴上。当您接近无穷大时,它们在 0 附近更加密集,并且相距非常远。因此,没有可以添加到浮点数以获取下一个浮点数的常量。
Floating point numbers are not spread out uniformly over the number line like integer types are. They are more densely packed near 0 and very far apart as you approach infinity. Therefore there is no constant that you can add to a floating point number to get to the next floating point number.
您的代码格式不正确。您尝试将最小双精度值相加,并期望结果与原始值不同。问题是 double.MinValue 太小,结果被四舍五入并且不受影响。
建议阅读:http://en.wikipedia.org/wiki/Machine_epsilon
维基百科文章也是Java代码。 Epsilon 根据定义是最小的数字,例如 (X + eps * X != X),eps*X 称为“相对 epsilon”
Your code is not well-formed. You try to add the minimum double value and expect the result to be different from the original value. The problem is that double.MinValue is so small that the result is rounded and doesn't get affected.
Suggested reading: http://en.wikipedia.org/wiki/Machine_epsilon
On the Wikipedia article there is the Java code too. Epsilon is by definition the smallest number such as (X + eps * X != X), and eps*X is called "relative-epsilon"
从 Java 1.8 开始,
java.lang.Math.nextUp(double)
完全可以满足您的需求。还有相反的java.lang.Math.nextDown(double)
。Since Java 1.8 there is
java.lang.Math.nextUp(double)
doing exactly what you want. There is also oppositejava.lang.Math.nextDown(double)
.如果您想使用 BigDecimal 类,还有
BigDecimal.ulp()
方法。In case you want to use the BigDecimal class, there is the
BigDecimal.ulp()
method as well.总体思路是首先将 double 转换为其 long 表示形式(使用
doubleToLongBits
正如您在getRealBinary
中所做的那样),将该 long 加 1,最后将新的 long 转换回来通过longBitsToDouble
转换为它所代表的双精度数。编辑:Java(自1.5起)提供了Math.ulp(double),我猜你可以用它来直接计算下一个更高的值,因此:x + Math.ulp(x) 。
The general idea is first convert the double to its long representation (using
doubleToLongBits
as you have done ingetRealBinary
), increment that long by 1, and finally convert the new long back to the double it represents vialongBitsToDouble
.EDIT: Java (since 1.5) provides
Math.ulp(double)
, which I'm guessing you can use to compute the next higher value directly thus:x + Math.ulp(x)
.