我有关于双精度的问题。当浮点值传递给双精度时,我会得到一些不同的结果。例如
float f= 54.23f;
double d1 = f;
System.out.println(d1);
输出为 54.22999954223633。有人可以解释这种行为背后的原因。是否像 double 默认为 14 位小数精度。
我有关于双精度的问题。当浮点值传递给双精度时,我会得到一些不同的结果。例如
float f= 54.23f;
double d1 = f;
System.out.println(d1);
输出为 54.22999954223633。有人可以解释这种行为背后的原因。是否像 double 默认为 14 位小数精度。
相同的值打印不同float
,double
因为 Java 规范要求打印尽可能多的数字,以区分相同类型的相邻可表示值的值(根据我在此处的回答,请参阅链接文档以获取更精确的定义)。
由于float
用于表示值的位更少,因此值也更少,因此它们之间的间距更大,并且您不需要那么多数字来区分它们。当您将值放入 adouble
并打印时,Java 规则要求打印更多的数字,以便将该值与附近的double
值区分开来。该println
函数不知道该值最初来自 afloat
并且不包含尽可能多的信息以适合 a double
。
54.23f
正好是 54.229999542236328125(十六进制,0x1.b1d70ap+5)。float
刚好低于和高于此值的值为 54.2299957275390625 (0x1.b1d708p+5) 和 54.23000335693359375 (0x1.b1d70cp+5)。如您所见,打印“54.229999”会将值与 54.229995... 和 54.23... 区分开来。但是,double
正下方和正上方的值54.23f
是 54.22999954223632101957264239899814128875732421875 和 54.22999954223633523042735760100185871124267578125。要区分值,您需要“54.22999954223633”。
这是由于内部代表。
浮点数通常作为符号位、指数字段和有效数(尾数)从左到右打包到计算机数据中。
这称为准确性问题。
浮点数不能精确地表示所有实数,浮点运算也不能精确地表示真正的算术运算,这一事实导致了许多令人惊讶的情况。这与计算机通常表示数字的有限精度有关。
这不成问题。这就是双重的工作方式。您不必处理它并关心它。double 的精度就足够了。想一想,你的数字和预期结果之间的差异在小数点后的第 14 位。
如果您需要任意良好的精度,请使用java.math.BigDecimal
该类。
或者,如果您仍想使用双精度。这样做:
double d = 5.5451521841;
NumberFormat nf = new DecimalFormat("##.###");
System.out.println(nf.format(d));
如有任何疑问,请告诉我。
实际上这只是关于不同的视觉表示或将浮点/双精度转换为字符串。让我们看一下内部二进制表示
float f = 0.23f;
double d = f;
System.out.println(Integer.toBinaryString(Float.floatToIntBits(f)));
System.out.println(Long.toBinaryString(Double.doubleToLongBits(d)));
输出
111110011010111000010100011111
11111111001101011100001010001111100000000000000000000000000000
这意味着f
转换为d1
没有任何失真,有效数字相同
这是因为 float 隐藏了多余的小数,而 double 显示了它们。双精度将非常精确地表示实际数字并显示更多数字。
尝试这个:
System.out.println(f.doubleValue()); (当然首先需要使它成为一个浮点数)
如您所见,信息就在那里,只是四舍五入。希望这可以帮助
double
并float
以不同的格式表示数字。
因此,您一定会发现某些数字可以完美地以一种格式存储,但不能以另一种格式存储。您碰巧找到了一个正确地适合 afloat
但不适合exactly
`double。
当使用两种不同的格式化程序时,也会出现此问题。