MySQL圆奇怪的bug

时间:2012-05-04 09:54:15

标签: php mysql

我面临着一个非常奇怪的错误?现在在mysql + php上。 是一个简单的选择,在下面的例子中,我使用多个字段来尝试解释我的问题:

  • “field”是11.5
  • $ phpvar是1.15

MySQL查询:

select round(field * " . $phpvar . " ,2) as a1, 
       round(field * 1.15 ,2) as a2, 
       round(11.5 * " . $phpvar . " ,2) as a3, 
       round(11.5 * 1.15 ,2) as a4, 
       field * " . $phpvar . " as a5 
from ...
好吧,我想要得到13.23。 "field" * $phpvar = 13.225,所以使用round(13.225,2)我应该得到13.23,对吧?好吧,是的,没有。

查询结果:

  • a1 [round(field *“。$ phpvar。”,2)] => 13.22
  • a2 [round(field * 1.15,2)] => 13.22
  • a3 [round(11.5 *“。$ phpvar。”,2)] => 13.23
  • a4 [round(11.5 * 1.15,2)] => 13.23
  • a5 [field *“。$ phpvar。”] => 13.225(无圆)
我错过了什么?怎么可能,当谈到使用“领域”时,我的结果是假轮?

2 个答案:

答案 0 :(得分:8)

问题是如何存储DOUBLE和FLOAT值。

有可能(并且可能)像11.5或22.475这样的值存储在近似值中,如11.499999999999~或22.475000000000000001,因此某些计算或舍入可能会导致错误的结果。

将浮点值存储到 DECIMAL coulmn类型中总是更好,其中值与所有十进制数字完全一致地存储,并且不是近似值。

答案 1 :(得分:5)

精确的数字文字(例如所有四个示例中的1.15和后两个中的11.5)使用MySQL的DECIMAL类型encoded

在前两个示例中,将field(类型DOUBLE)与此类文字相乘的结果是另一个DOUBLE,使用8-byte {{3}存储浮点表示(即IEEE Standard)。但是,在此表示中13.225编码为0x402A733333333333,其位代表:

Sign           : 0b0

Biased exponent: 0b10000000010
               =   1026 (representation includes bias of +1023, therefore exp = 3)

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

这相当于:

  (-1)^0 * 1.6531249999999999555910790149937383830547332763671875 * 2^3
=         13.2249999999999996447286321199499070644378662109375000

因此,将此结果四舍五入到小数点后两位会产生13.22而不是13.23

使用两个DECIMAL类型进行乘法运算,例如后两个示例中使用的两个文字,会产生另一个DECIMAL。在此表示中,13.225binary64格式进行编码,具有精确的精度,因此舍入操作会按预期生成13.23

binary-coded decimal中所述:

  

浮点数有时会引起混淆,因为它们是近似值而不是存储为精确值。在SQL语句中写入的浮点值可能与内部表示的值不同。尝试将浮点值视为比较中的精确值可能会导致问题。它们还受平台或实现依赖性的影响。 MySQL manualFLOAT数据类型受这些问题的影响。对于DOUBLE列,MySQL执行精度为65位十进制数的运算,这可以解决最常见的不准确问题。

如果您精确准确,DECIMAL可能更符合您的要求。如果您需要DOUBLE的范围/效果但仍希望获得所需的舍入结果,则可以在舍入之前将DECIMAL乘以DECIMAL的结果。

相关问题