了解在PHP浮点数(Understanding floating point numbers in

2019-09-18 00:36发布

我知道,这些问题可能会问了很多,但是从我的阅读和测试它让我困惑了一下,很多我也做了阅读刚刚困惑我更因为它是相当复杂的。

有些人似乎有比较简单的问题,但我有没有问题我自己。

例如...

$num1 = 27.64;
$num2 = 27.64;

if ($num1 == $num2) {
    echo 'Good!';
} else {
    echo 'Bad!';
}

// Echo's "Good!"

...和

$num1 = 27.60;
$num2 = 27.6;

if ($num1 == $num2) {
    echo 'Good!';
} else {
    echo 'Bad!';
}

// Echo's Good

...和

$num1 = 27.60;
$num2 = 57.60;

if ($num1 <= $num2) {
    echo 'Good!';
} else {
    echo 'Bad!';
}

// Echo's Good

...和

$num1 = 25.00;
$num2 = 12.50 + 12.5;

if ($num1 == $num2) {
    echo 'Good!';
} else {
    echo 'Bad!';
}

// Echo's Good

然后,我看到这样的页面http://patchlog.com/php/comparing-float-values-in-php/ ,似乎有简单的问题,我不明白这一点。

我只是想了解他是如何获得的问题与他简单的代码,但我不与我。

Answer 1:

实施例1

这些值将是相同的 - 你分配相同的十进制文本到每个变量。 与此相比,这样的代码:

$num1 = 27.64;
$num2 = 10.0 + 2.88 + 2.88 + 2.88 + 9.0; //In decimal arithmetic adds to 27.64

if ($num1 == $num2) {
    echo 'Good!';
} else {
    echo 'Bad!';
}

// Echo's "Bad!"

$ NUM2看起来应该是27.64,但它确实增加了类似27.639999999999997015720509807579219341278076171875(这就是我得到的,当我做计算在Visual C ++我的机器上)。 $ NUM1 = 27.6400000000000005684341886080801486968994140625(我的机器上),所以它们之间的区别。

实施例2

尾随0没什么区别。

实施例3

这些数字是不是浮点“宽容”中这样当然会有所不同。

实施例4

12.5是在浮点精确表示,所以12.5 + 12.5太(0.5是2 ^ -1)。



Answer 2:

这是一个明显的例子:

$a = 0;
for ($i = 0; $i < 100000; $i++) {
    $a += 0.00001;
}
print("$a\n");

你可能会认为你会得到1打印,但实际上输出为0.99999999999808

(结果是上x86_64体系)



Answer 3:

更大的(或更小)的浮点数,则不太精确它是。 究竟如何精确将基于处理器体系结构。

尝试1E30或1E30做所有的测试...



Answer 4:

前两个具有由编译器,这是解决这两个数字到相同的位模式提供的值。

我不会碰第三,因为它应该是显而易见的,为什么它的工作原理。

对于第四,使用的值具有明确定义的,完全准确的位模式。 尝试使用数字多一点因循守旧。



Answer 5:

你可以试试

 $a = '12.30';

作为字符串获得通过结束“0”默认删除,否则floatbox精确匹配。



Answer 6:

当有业务,其数学成绩不能在浮点精确表示只发生浮点错误。 该错误被精确定义; 它们不是随机或任意的,所以当进行相同的操作相同的结果产生的。

在你的第一个例子中,可以分配“27.64”到$ NUM1和$ NUM2。 这里有正在执行操作:解析器必须解释字符串“27.64”,并产生一个浮点结果。 很有可能,解析器产生浮点数是最接近27.64。 (作为一个十六进制浮点数字,这个数字是0x1.ba3d70a3d70a4p + 4。的“P”之前的部分是一个十六进制数字,具有小数部分。所述的“P4”由2 4乘法装置,其十进制数,它是27.6400000000000005684341886080801486968994140625。)以及它产生在两种情况下相同的编号,所以$ NUM1到$ NUM2指示它们是彼此相等的比较,虽然也不是等于27.64(因为27.64不能被精确在浮点表示)。

在第二示例中,最接近于数字“27.60”的值的浮点数是一样的浮点数的最接近的数字“27.6”的值,由于两个数字表示相同的值。 所以,再一次,你会得到相同的结果。

在你的第三个例子,这两个数字的值相距甚远,所以你会得到不同的浮点数,和比较表明他们是不平等的。

在你的第四个例子,所有的值都是浮点精确表示,因此不存在错误。 25,12.50和12.5是二的幂的所有小倍数(包括具有负指数的权力,诸如0.5 = 2 -1,浮点型的范围内,因此它们是可表示的。另外,在的12.50和12.5总和是精确表示,所以将它们添加时没有舍入误差。因此,所有的结果是精确的,并且该比较指示之和等于25。

当人们期待从两个不同的计算相同的结果,将具有相同的数学结果会出现问题。 一个典型的例子就是“0.3”进行比较来“0.1 + 0.2”。 转换的数字“0.3”,以浮点产生最接近的表示值,其是0x1.3333333333333p-2(0.299999999999999988897769753748434595763683319091796875),略低于0.3。 转换“0.1”,以浮点产生最接近的表示值,其是0x1.999999999999ap-4(0.1000000000000000055511151231257827021181583404541015625),略超过0.1。 转换“0.2”,以浮点产生最接近的表示值,其是0x1.999999999999ap-3(0.200000000000000011102230246251565404236316680908203125),略超过0.2。 添加后两个值接近的产生了表示值到它们的总和,这是0x1.3333333333334p -2(0.3000000000000000444089209850062616169452667236328125)。 正如你所看到的,那笔是从。“3”转换为浮点所得的值不同,所以比较它们表示它们不相等。



文章来源: Understanding floating point numbers in php