Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 浮点到双赋值_Java_Floating Accuracy_Approximation_Double Precision - Fatal编程技术网

Java 浮点到双赋值

Java 浮点到双赋值,java,floating-accuracy,approximation,double-precision,Java,Floating Accuracy,Approximation,Double Precision,考虑下面的代码片段 float num = 281.583f; int amount = (int) Math.round(num*100f); float rounded = amount/100.0f; double dblPrecision = rounded; double dblPrecision2 = num; System.out.println("num : " + num + " amount: " + amount + " rounded: " + rounded + " d

考虑下面的代码片段

float num = 281.583f;
int amount = (int) Math.round(num*100f);
float rounded = amount/100.0f;
double dblPrecision = rounded;
double dblPrecision2 = num;
System.out.println("num : " + num + " amount: " + amount + " rounded: " + rounded + " dbl: " + dblPrecision + " dbl2: " + dblPrecision2);
我得到的输出是

num : 281.583 amount: 28158 rounded: 281.58 dbl: 281.5799865722656 dbl2: 281.5830078125

当一个浮点数被分配给一个双变量时,为什么会有近似值呢?

当您将小数转换为
浮点数时,实际上会出现近似值。我可能会让你感到惊讶,但是
281.583
在PC中不能准确地表示为浮点数。这是因为浮点数在PC中表示为二进制分数之和。
0.5
0.25
0.125
可以精确转换,但不能
0.583

浮点数(和双精度浮点数)表示为
∑(1/2^i*Bi)
,其中
Bi
是第i位
(0 | 1)
<例如,代码>0.625=1/2+1/4
。问题是并非所有的十进制分数都能转换成二进制分数的有限和

下面是该数字的转换方式(第一行是列定义)


近似值始终存在。碰巧的是,double提供了足够多的额外比特,使得额外的东西显示出来

例如,281.583是二进制的(许多数字,但小于双精度): 100011001.1001\U 0101\U 0011\U 1111\U 0111\U 1100\U 1110\U 1101\U 1001

Float允许大约23位,double允许大约52位。(记不清了) 100011001.1001_0101_0011_11,十进制为281.582946777

作为参考,单精度存储约7位小数,双精度存储约16位小数。这包括了所有的数字,所以你的数字只比浮点数的精度低1位数。

因为浮点数是二进制分数,因此只能近似地表示十进制数。当源代码中的文字
281.583f
被解析为IEEE 754浮点值时,就会出现近似值

对于浮动本身,这一点被掩盖了,因为

同样多,但只有同样多,更多的数字 作为唯一的区分所需要的 来自相邻参数的参数值 float类型的值

在许多情况下,这意味着将打印文本的十进制值。但是,当您将值分配给
double
时,“double类型的相邻值”通常比
float
类型的值更接近,因此您可以看到近似float的真实值


有关更多详细信息,请阅读。

据我所知,您关心的是,为什么要使用此代码

float f = 281.583f;
System.out.println(f);
System.out.println((double) f);
…印刷品

281.583
281.5830078125
(嘿,double提供了更高的精度!)

这就是为什么

438ccaa0
(表示
281.583f
的位的十六进制格式,如
Integer.tohextstring(Float.floatToRawIntBits(281.583f))
所示)输入到表单中。您将看到,浮点实际上表示为
281.58301
。(@Michael Borgwardt回答了为什么它不是那样印刷的。)

因此,当表示为浮点数时,将为
281.58301
打印
281.583
。但是当你把
281.58301
转换成双精度时,你实际上可以比
281.583
更接近
281.58301


查看上述网页的计算结果,您可以得到接近于281.58300781250000的值,这就是为什么您会看到值281.5830078125被打印出来的原因。

简而言之,除非确实需要,否则不要使用float。您将失去精度,可能节省很少。使用双倍,你将避免很多悲伤

double num = 281.583;
long amount = (long) (num*100);
double rounded = (double) amount/100;
double dblPrecision = rounded;
double dblPrecision2 = num;
印刷品

num : 281.583 amount: 28158 rounded: 281.58 dbl: 281.58 dbl2: 281.583

浮动和双精度在内部实际上具有相同的值;它们只是印刷方式不同而已。将这些行添加到您的程序中,以十六进制方式查看它们:

System.out.printf("num:           %a\n",num);
System.out.printf("dblPrecision2: %a\n",dblPrecision2);

System.out.printf("rounded:       %a\n",rounded);
System.out.printf("dblPrecision:  %a\n",dblPrecision);
这张照片

num:           0x1.19954p8
dblPrecision2: 0x1.19954p8
rounded:       0x1.19947ap8
dblPrecision:  0x1.19947ap8
num=dblPrecision2,四舍五入=dblPrecision


现在0x1.19954p8=100011001.100101010100=281.5830078125,0x1.19947ap8=100011001.100101000111010=281.57998657226625。所发生的一切是,它们在打印时的取整方式不同(浮点数取整到的位数小于双精度浮点数)。

是的,这是所有双精度浮点数的问题。这与作业无关。@Erick Robertson这就是我要解释的。将浮点转换为双精度并不能“让你更接近”精度的损失;你得到了同样的近似值(见我的答案)。@Rick,仔细阅读。它使您比为浮点表示打印的值更接近。但是您写道“但是当您将281.58301转换为双精度时,您实际上可以比281.583更接近281.58301”。关键是打印,而不是转换。如果你用“printf(%.17f”)”来打印,两者给出的答案都是一样的——281.5830078125000000。顺便说一句,我假设你是指问题中的浮点到双精度转换——281.583。你有没有提出一个不同的观点,关于直接给一个双人间分配一个不同的号码281.58301?如果是这样的话,那么就得到了281.583010000000001582520781084895133972176796875。
num:           0x1.19954p8
dblPrecision2: 0x1.19954p8
rounded:       0x1.19947ap8
dblPrecision:  0x1.19947ap8