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

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

    $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),此代码之前工作正常.我不确定这里出了什么问题.你能指出我正确的方向吗?
谢谢!

解决方法:

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

MysqL performs rounding when storing values, so if you insert 999.00009 into a FLOAT(7,4) column, the approximate result is 999.0001.

Because floating-point values are approximate and not stored as exact values, attempts to treat them as exact in comparisons may lead to problems. They are also subject to platform or implementation dependencies. For more information, see 07001

For maximum portability, code requiring storage of approximate numeric data values should use FLOAT or DOUBLE PRECISION with no specification of precision or number of digits.

因此,在将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.

相关文章

统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
前言 之前做了微信登录,所以总结一下微信授权登录并获取用户...
FastAdmin是我第一个接触的后台管理系统框架。FastAdmin是一...
之前公司需要一个内部的通讯软件,就叫我做一个。通讯软件嘛...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...