3

我猜这之前已经出现过,但我找不到我的问题的答案。这是一个小代码片段:

    $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),并且这段代码之前运行良好。我不确定这里出了什么问题。你能指出我正确的方向吗?谢谢!

4

2 回答 2

4

浮点类型(近似值) - FLOAT, 中DOUBLE所述:

MySQL 在存储值时会进行舍入,因此如果插入999.00009FLOAT(7,4)列中,则近似结果为999.0001.

因为浮点值是近似值而不是存储为精确值,所以在比较中尝试将它们视为精确值可能会导致问题。它们还受平台或实现依赖关系的影响。有关详细信息,请参阅第 C.5.5.8 节,“浮点值问题”</a>

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

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

符号           :0b0

有偏指数:0b01111111
               = 127(表示包括 +127 的偏差,因此 exp = 0)

有效    数字:0b[1.]11001100110011001100110
                    ^ 隐藏位,不以二进制表示形式存储
               = [1.]7999999523162841796875

这相当于:

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

这是 MySQL 返回给客户端的值。看起来 AdoDB 然后检查了列的数据类型并相应地对结果进行了四舍五入,而 PDO 没有。

如果您想要精确的值,您应该使用定点数据类型,例如DECIMAL.

于 2013-06-11T15:59:12.890 回答
1

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

于 2013-06-11T15:38:13.737 回答