Kel*_*nch 1 java floating-point
替代措辞:何时将Double.MIN_VALUE添加到Java中的double 不会导致不同的Double值?(见Jon Skeet的评论如下)
关于Java中最小Double值的这个问题有一些答案在我看来是等价的. Jon Skeet的回答无疑是有效的,但他的解释并没有让我相信它与理查德的 答案有什么不同.
Jon的回答使用以下内容:
double d = // your existing value;
long bits = Double.doubleToLongBits(d);
bits++;
d = Double.longBitsToDouble();
Run Code Online (Sandbox Code Playgroud)
理查兹回答提到了JavaDoc Double.MIN_VALUE
保持double类型的最小正非零值的常量,2-1074.它等于十六进制浮点字面值0x0.0000000000001P-1022并且也等于
Double.longBitsToDouble(0x1L).
我的问题是,Double.logBitsToDouble(0x1L)与Jon的不同之处bits++;有何不同?
Jon的评论侧重于基本的浮点问题.
将Double.MIN_VALUE添加到double值和增加表示double的位模式之间存在差异.由于存储浮点数的方式,它们是完全不同的操作.如果您尝试将一个非常小的数字添加到一个非常大的数字,差异可能很小,以至于最接近的结果与原始数字相同.但是,在当前位模式中添加1将始终将相应的浮点值更改为在该比例下可见的最小可能值.
我没有看到Jon添加Double.MIN_VALUE增加长"bit ++"的方法有什么不同.他们何时会产生不同的结果?
我编写了以下代码来测试差异.也许有人可以提供更多/更好的样本双数或使用循环来找到存在差异的数字.
double d = 3.14159269123456789; // sample double
long bits = Double.doubleToLongBits(d);
long bitsBefore = bits;
bits++;
long bitsAfter = bits;
long bitsDiff = bitsAfter - bitsBefore;
long bitsMinValue = Double.doubleToLongBits(Double.MIN_VALUE);
long bitsSmallValue = Double.doubleToLongBits(Double.longBitsToDouble(0x1L));
if (bitsMinValue == bitsSmallValue)
{
System.out.println("Double.doubleToLongBits(0x1L) is same as Double.doubleToLongBits(Double.MIN_VALUE)");
}
if (bitsDiff == bitsMinValue)
{
System.out.println("bits++ increments the same amount as Double.MIN_VALUE");
}
if (bitsDiff == bitsMinValue)
{
d = d + Double.MIN_VALUE;
System.out.println("Using Double.MIN_VALUE");
}
else
{
d = Double.longBitsToDouble(bits);
System.out.println("Using doubleToLongBits/bits++");
}
System.out.println("bits before: " + bitsBefore);
System.out.println("bits after: " + bitsAfter);
System.out.println("bits diff: " + bitsDiff);
System.out.println("bits Min value: " + bitsMinValue);
System.out.println("bits Small value: " + bitsSmallValue);
Run Code Online (Sandbox Code Playgroud)
OUTPUT:
Double.doubleToLongBits(Double.longBitsToDouble(0x1L)) is same as Double.doubleToLongBits(Double.MIN_VALUE)
bits++ increments the same amount as Double.MIN_VALUE
Using doubleToLongBits/bits++
bits before: 4614256656636814345
bits after: 4614256656636814346
bits diff: 1
bits Min value: 1
bits Small value: 1
Run Code Online (Sandbox Code Playgroud)
好吧,让我们用这种方式想象它,坚持使用十进制数字.假设您有一个浮点小数点类型,它允许您表示5个十进制数字,以及指数为0到3之间的数字,将结果乘以1,10,100或1000.
因此,最小的非零值仅为1(即尾数= 00001,指数= 0).最大值是99999000(尾数= 99999,指数= 3).
现在,当您添加1到50000000时会发生什么?你不能代表50000001 ... 5亿之后的下一个表示数为50001000.所以,如果你试图把它们加在一起,结果只是将是最接近的值到"真"的结果-这仍然是500000000.这是喜欢加入Double.MIN_VALUE一个大的double.
我的版本(转换为位,递增然后转换回来)就像取50000000,分为尾数和指数(m = 50000,e = 3)然后将其递增到最小量,到(m = 50001,e = 3)然后重新组装到50001000.
你看到他们有什么不同吗?
现在这是一个具体的例子:
public class Test{
public static void main(String[] args) {
double before = 100000000000000d;
double after = before + Double.MIN_VALUE;
System.out.println(before == after);
long bits = Double.doubleToLongBits(before);
bits++;
double afterBits = Double.longBitsToDouble(bits);
System.out.println(before == afterBits);
System.out.println(afterBits - before);
}
}
Run Code Online (Sandbox Code Playgroud)
这会尝试大量的两种方法.输出是:
true
false
0.015625
Run Code Online (Sandbox Code Playgroud)
通过输出,这意味着:
Double.MIN_VALUE没有任何影响afterBits,并before为0.015625,这是很多比我的大Double.MIN_VALUE.难怪简单的添加没有效果!