2

我对 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 - 这可以工作,以 1 为增量输出 0-20。

最小值:0.2,最大值:3,步长:0.2 - 这不起作用,以 0.2 为增量输出 0.2 到 2.8,但不输出 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() 的检查。如果它是一个整数,我将去除小数并尾随零以保持显示清洁度。可能有更直接的方法可以做到这一点,但这非常有效。

再次感谢大家!

4

6 回答 6

3

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

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

于 2013-10-01T22:01:30.840 回答
2

浮点数存储为二进制十进制数据,并且始终是实数的近似值。因此,多次添加 0.3 可能会像 15 但那不是 15。为了解决您的问题,将任何数字乘以一个因子(10 或 100)以仅适用于整数。

于 2013-10-01T22:02:55.317 回答
1

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

于 2013-10-01T22:01:38.403 回答
1

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

您可以使用 bc 数学来防止浮点错误:

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

于 2013-10-01T22:05:21.560 回答
0

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

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

于 2013-10-01T22:02:16.923 回答
0

尝试将所有值转换为浮点数。似乎这里可能存在精度问题。

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

于 2013-10-01T22:05:44.423 回答