我猜这个已经出现了,但我找不到我的问题的答案.这是一个小代码片段:
$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 aFLOAT(7,4)
column, the approximate result is999.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
orDOUBLE 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.