我猜这个已经出现了,但我无法找到问题的答案。这是一个小代码片段:
$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),此代码之前工作正常。我不确定这里出了什么问题。你能指出我正确的方向吗? 谢谢!
答案 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”
为了获得最大的可移植性,需要存储近似数值数据值的代码应使用
FLOAT
或DOUBLE 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与它无关。它与计算机的工作方式有关。