为什么float在Python / PHP / Javascript和Java / C#之间表现不同

时间:2017-07-16 09:00:32

标签: java c# python floating-point precision

10年后,我(重新)学习Java,我正在编写简单的代码,以便检查语法并验证简单的行为。 我正在玩数字类型,我不明白为什么浮点数在Java(以及后面验证的C#)中的行为与Python(或其他脚本语言,如JavaScript或PHP)不同。 关键在于,根据我的知识,当精度很重要时浮点数是不可靠的,而我想到的最简单的例子之一就是总和:

float(0.1) + float(0.2)

不同于人们所期望的不是float(0.3),而是float(0.30000000000000004),因为"在幕后问题四舍五入"。 所以,在我的虚拟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#这样的编译语言表现不同?

1 个答案:

答案 0 :(得分:9)

脚本语言和Java / C#之间没有区别。但是,floatdouble之间存在差异。在脚本语言中(至少在Python中),float的基础类型通常具有64位精度(即Java中的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。然而,这不是一般结果,对于许多其他数字,这将不成立。因此,浮子仍然不可靠,精确度很高。