PHP PDO查询返回FLOAT字段的不准确值

时间:2013-06-11 15:30:53

标签: php mysql pdo

我猜这个已经出现了,但我无法找到问题的答案。这是一个小代码片段:

    $stmt = $this -> db -> query("
        SELECT
          `Field`
        FROM
          `Table`
        WHERE
          (`ID` = 33608)");
    var_dump($stmt -> fetch());

这是我得到的结果:

    array(1) { ["Field"]=> float(1.7999999523163) }

但是,MySQL数据库中的数据是1.8。字段的类型是float(7,4)。 $ this-> db是一个PDO对象。 我最近迁移到PDO(来自AdoDB),此代码之前工作正常。我不确定这里出了什么问题。你能指出我正确的方向吗? 谢谢!

2 个答案:

答案 0 :(得分:4)

正如Floating-Point Types (Approximate Value) - FLOAT, DOUBLE所述:

  

MySQL在存储值时执行舍入,因此如果您将999.00009插入FLOAT(7,4)列,则大致结果为999.0001

     

由于浮点值是近似值而未存储为精确值,因此尝试在比较中将它们视为精确值可能会导致问题。它们还受平台或实现依赖性的影响。有关详细信息,请参阅Section C.5.5.8, “Problems with Floating-Point Values”

     

为了获得最大的可移植性,需要存储近似数值数据值的代码应使用FLOATDOUBLE PRECISION,而不指定精度或位数。

因此,在将1.8插入数据库后,MySQL将文字四舍五入为001.8000并将最接近的近似值编码为binary32格式的数字:即0x3FE66666,其位代表:

Sign           : 0b0

Biased exponent: 0b01111111
               =   127 (representation includes bias of +127, therefore exp = 0)

Significand    : 0b[1.]11001100110011001100110
                    ^ hidden bit, not stored in binary representation
               =   [1.]7999999523162841796875

这相当于:

 (-1)^0 * 1.7999999523162841796875 * 2^0
=         1.7999999523162841796875

这是MySQL返回给客户端的值。看来AdoDB会检查列的数据类型并相应地舍入结果,而PDO则没有。

如果您需要准确的值,则应使用fixed point datatype,例如DECIMAL

答案 1 :(得分:1)

如果您想要准确的值,则必须使用DECIMAL字段类型而不是FLOAT 而PDO与它无关。它与计算机的工作方式有关。