为什么使用浮点数和间隔时,range()函数不包括终止值?

8

文档表明范围的$end是包含在内的。大多数情况下确实如此,但是当$end$step都是浮点数时,最后一个值会丢失。为什么呢?

print_r(range(1, 13, 1));
print_r(range(1, 13, 0.1));
print_r(range(0.1, 1.3, 0.1));

输出:

Array
(
    [0] => 1
    [1] => 2
    // ...
    [11] => 12
    [12] => 13
)
Array
(
    [0] => 0.1
    [1] => 0.2
    // ...
    [119] => 12.9
    [120] => 13
)
Array
(
    [0] => 0.1
    [1] => 0.2
    // ...
    [10] => 1.1
    [11] => 1.2
    // 12 => 1.3 is missing
)

2
浮点数是近似值。当你增加0.1时,不一定总能精确到达终点。 - Barmar
1
是的,看起来是PHP7 https://3v4l.org/kp1Fv - AbraCadaver
但在 for 循环中似乎没问题:https://3v4l.org/IgD6t - AbraCadaver
1
看起来类似的问题已经在7.0.5中被报告并修复了 https://bugs.php.net/bug.php?id=72017 - nCrazed
解决方法:将您的另外两个范围构造为print_r(range(10,130,1))print_r(range(10,13,1)),然后分别将它们的所有值除以10.0和10.0。 - feedMe
显示剩余5条评论
1个回答

4

这个范围是包括在内的;然而,你对数字加起来的假设是不正确的。

0.1 无法用精确的二进制表示。当你在php中进行计算时,实际上会得到一个略高或略低的数字。请看下面的代码片段:

http://codepad.org/MkoWgAA1

<?php

$sum = 1.0 + 0.1 + 0.1;

if ($sum > 1.2) {
  print("1.2 > 1.2");
} else if ($sum < 1.2) {
  print("1.2 < 1.2");
} else {
  print("1.2 == 1.2");
}

输出:

1.2 > 1.2

有趣的是,这在3v4l支持的所有版本上产生了完全相同的结果,而我的示例在5.6-7.0.2版本(以及HHVM)上产生了预期的结果,但在7.0.3-7.1.1版本上会出现浮点精度问题。 - nCrazed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接