PHP For循环有时停止太早

时间:2013-10-01 21:56:02

标签: php for-loop

我对for循环有一个奇怪的问题。我正在将一个数组传递给一个函数,该函数根据三个数组键输出值(它实际上创建了一个选择框):select_min,select_max和select_step。大部分时间,它都有效。有时它不会增加最后时间。我也尝试过对不能正常工作的值进行硬编码。

代码是:

for( $a = $property['select_min']; $a <= $property['select_max']; $a += $property['select_step'] ) {
    echo $a . "<br/>";
}

我用0.1到1.2的“步长”测试了它。我无法弄清楚为什么它在某些情况下不起作用。它似乎只是十进制值的问题。

最小值:0,最大值:20,步骤:1 - 此方法有效,输出0-20,增量为1。

最小值:0.2,最大值:3,步长:0.2 - 这不起作用,输出0.2到2.8,增量为0.2,但不输出3.无论我放的是什么,似乎总是失败。 ..当我从0到22运行它时它起作用了。

最小值:0,最大值:7,步骤:0.7 - 这不起作用。不输出7。

有趣的案例:

最小值:0,最大值:3,6或9,步骤:0.3 - 工作

最小值:0,最大值:12或15,步骤:0.3 - 不起作用

我已经完成了许多其他测试,并且找不到一个共同的线程,为什么它在这些特定实例中不起作用。

编辑: 感谢所有的回复。我最终使用了Petah的解决方案并提出了这个问题:

for( $a = $property['select_min']; 
    bccomp( $a , $property['select_max'] , 1 ) <= 0; 
    $a = bcadd( $a , $property['select_step'] , 1 ) ) {
        $str_editor_html .= '<option value="' . ( !is_float( $property['select_step'] ) ? str_replace( ".0" , "" , $a ) : $a ) . '"' . ( strval( $value['setting'] ) == strval( $a ) ? ' SELECTED' : '' ) . '>' . ( !is_float( $property['select_step'] ) ? str_replace( ".0" , "" , $a ) : $a ) . '</option>';
}

我在“step”变量上添加了对!is_float()的检查。如果它是一个整数,我将剥离小数并且尾随零以显示清洁度。可能有更直接的方法可以做到这一点,但这很有效。

再次感谢,你们呀!

6 个答案:

答案 0 :(得分:3)

请参阅以下http://php.net/manual/en/language.types.float.php

基本上,在php中,对比较浮点数并不能保证。在上面的链接中,有一个红色框,其中包含问题描述以及可以使用的内容。

答案 1 :(得分:2)

浮点数存储为二进制十进制数据,并且始终是实数的近似值。所以可能会发生这样的情况:多次添加0.3会是15次,但不是15次。 要解决您的问题,请将任意数字乘以因子(10或100),以便仅使用整数。

答案 2 :(得分:1)

浮点数是近似值。二进制值使用基数2,因此使用1/2,1 / 4,1 / 8 ......之和计算。这不能给出小数0.2或0.3的有限精确值。因此存在一个小的误差,并且重复添加相同的值只会扩大该误差。

答案 3 :(得分:1)

正如其他人所说,这是因为浮点精度。

您可以使用bc math来防止浮动错误:

for ($a = $property['select_min']; 
        bccomp($a, $property['select_max'], 2) <= 0; 
        $a = bcadd($a, $property['select_step'], 2)) {
    echo $a . "<br/>";
}

http://www.php.net/manual/en/ref.bc.php

在此处查看此行动:http://codepad.viper-7.com/dBOmGR

答案 4 :(得分:0)

浮点值的精度有限,所以当你做2.0 + 0.1时,它不会完全是2.1。

解决这个问题的最简单方法是使用整数,例如:从20开始,递增1,当你需要值时,总是除以10。

答案 5 :(得分:0)

尝试将所有值转换为浮点数。看来这里可能存在精确问题。

或者,尝试使用浮动的所有整数表示,即乘以10(对于您提供的示例)。