为什么 float 在 Python/PHP/Javascript 和 Java/C 之间表现不同#
Why float behaves differently between Python/PHP/Javascript and Java/C#
10 年后,我正在(重新)学习 Java 并且我正在编写简单的代码以检查语法并验证简单的行为。
我在玩数字类型,我不明白为什么浮点数在 Java(以及我后来验证的 C#)中的行为不同于 Python(或其他脚本语言,如 JavaScript 或PHP)。
关键是,据我所知,当精度很重要时,浮点数是不可靠的,我想到的最简单的例子之一就是总和:
float(0.1) + float(0.2)
不同于预期的不是 float(0.3)
,而是 float(0.30000000000000004)
由于 "rounding issues behind the scenes"。
所以,在我的虚拟 Java 代码中,我写了:
float wrongResult = 0.1f + 0.2f;
if (wrongResult != 0.3f) {
System.out.println("float sucks");
}
else {
System.out.println("float works");
}
double rightResult = 0.1 + 0.2;
if (rightResult != 0.3) {
System.out.println("double sucks");
}
else {
System.out.println("double works");
}
但输出却出乎意料:
float works
double sucks
这让我抓狂,因为 double 是 64 位类型而 float 只是 32 位类型,所以我希望得到相反的结果,因为 double 应该更精确。
所以我的巨大困境是:为什么像 Python、PHP 和 Javascript 这样的脚本语言的行为方式和像 Java 和 C# 这样的编译语言的行为方式不同?
脚本语言和Java/C#没有区别。但是,float
和double
是有区别的。一个小的混淆来自这样一个事实,即在脚本语言中(至少在 Python 中)float
的基础类型通常具有 64 位精度(即 [=21 中的 double
=]).那么,对于不同的行为,原因是四舍五入后最接近的值将不相同,从以下可以看出:
fl64(.1) == 0.10000000000000001
fl64(.2) == 0.20000000000000001
fl64(.3) == 0.29999999999999999
fl64(.1) + fl64(.2) == 0.30000000000000004
fl32(.1) == 0.1
fl32(.2) == 0.2
fl32(.3) == 0.30000001
fl32(.1) + fl32(.2) == 0.30000001
因此,精度较低(32 位)的恰好是 0.1 + 0.2 == 0.3
。然而,这不是一般结果,对于许多其他数字,这将不成立。因此,浮点数在精确度方面仍然不可靠。
10 年后,我正在(重新)学习 Java 并且我正在编写简单的代码以检查语法并验证简单的行为。 我在玩数字类型,我不明白为什么浮点数在 Java(以及我后来验证的 C#)中的行为不同于 Python(或其他脚本语言,如 JavaScript 或PHP)。 关键是,据我所知,当精度很重要时,浮点数是不可靠的,我想到的最简单的例子之一就是总和:
float(0.1) + float(0.2)
不同于预期的不是 float(0.3)
,而是 float(0.30000000000000004)
由于 "rounding issues behind the scenes"。
所以,在我的虚拟 Java 代码中,我写了:
float wrongResult = 0.1f + 0.2f;
if (wrongResult != 0.3f) {
System.out.println("float sucks");
}
else {
System.out.println("float works");
}
double rightResult = 0.1 + 0.2;
if (rightResult != 0.3) {
System.out.println("double sucks");
}
else {
System.out.println("double works");
}
但输出却出乎意料:
float works
double sucks
这让我抓狂,因为 double 是 64 位类型而 float 只是 32 位类型,所以我希望得到相反的结果,因为 double 应该更精确。 所以我的巨大困境是:为什么像 Python、PHP 和 Javascript 这样的脚本语言的行为方式和像 Java 和 C# 这样的编译语言的行为方式不同?
脚本语言和Java/C#没有区别。但是,float
和double
是有区别的。一个小的混淆来自这样一个事实,即在脚本语言中(至少在 Python 中)float
的基础类型通常具有 64 位精度(即 [=21 中的 double
=]).那么,对于不同的行为,原因是四舍五入后最接近的值将不相同,从以下可以看出:
fl64(.1) == 0.10000000000000001
fl64(.2) == 0.20000000000000001
fl64(.3) == 0.29999999999999999
fl64(.1) + fl64(.2) == 0.30000000000000004
fl32(.1) == 0.1
fl32(.2) == 0.2
fl32(.3) == 0.30000001
fl32(.1) + fl32(.2) == 0.30000001
因此,精度较低(32 位)的恰好是 0.1 + 0.2 == 0.3
。然而,这不是一般结果,对于许多其他数字,这将不成立。因此,浮点数在精确度方面仍然不可靠。