Php MySQL圆形怪虫

Php MySQL圆形怪虫,php,mysql,Php,Mysql,我正面临一个非常奇怪的虫子?现在在mysql+php上。 是一个简单的选择,在下面的示例中,我使用多个字段来解释我的问题: “字段”是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 *

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

  • “字段”是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[四舍五入(字段*“$phpvar.”,2)]=>13.22
  • a2[圆形(字段*1.15,2)]=>13.22
  • a3[圆形(11.5*“$phpvar.”,2)]=>13.23
  • a4[圆形(11.5*1.15,2)]=>13.23
  • a5[字段*“$phpvar.”]=>13.225(不含四舍五入)

我错过了什么?怎么可能,当使用“field”时,我的结果会得到一个假回合?

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

11.5或22.475等值可能(也可能)存储在11.4999999999~或22.475000000000000001等近似值中,因此某些计算或舍入可能导致错误结果

最好将浮点值存储到一个十进制coulmn类型中,该类型中的值与所有十进制数字一起存储,并且不是近似值。

精确的数字文字(例如所有四个示例中的
1.15
,以及后两个示例中的
11.5
)正在使用MySQL的
DECIMAL
类型

在前两个示例中,将
字段
(类型为
DOUBLE
)与此类文本相乘的结果是另一个
DOUBLE
,它使用浮点表示法存储(即)。然而,在此表示法中,
13.225
编码为
0x402A733333
,其位表示:

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 符号:0b0 有偏指数:0b10000000010 =1026(表示包括+1023的偏差,因此exp=3) 有效位:0b[1.]101001110011 = [1.]6531249999999999555910790149937383830547332763671875 ^隐藏位,不以二进制表示形式存储 这相当于:

(-1)^0 * 1.6531249999999999555910790149937383830547332763671875 * 2^3 = 13.2249999999999996447286321199499070644378662109375000 (-1)^0*1.6531249999995559107901499373383054733273671875*2^3 =13.224999999999964447286321199499070644378662109375000 因此,将该结果四舍五入到小数点后两位将产生
13.22
而不是
13.23

使用两个
DECIMAL
类型(如后两个示例中使用的两个文本)执行乘法,会产生另一个
DECIMAL
。在此表示法中,
13.225
以精确的格式进行编码,因此舍入操作会产生预期的
13.23

如报告中所述:

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


如果您追求精确精度,
DECIMAL
可能更适合您的要求。如果您需要
DOUBLE
的范围/性能,但仍希望获得所需的舍入结果,则可以在舍入之前将乘法结果转换为
DECIMAL

数据库中如何定义字段?选择字段*1.15和11.5*1.15,同时选择不舍入,以及a6和a7,然后公布结果。Anigel“字段”是双重的;;jishi select字段*1.15返回13.225;;选择11.5*1.15返回13.25;;Nick据我所知,mysql上的ceil()返回“不小于X的最小整数值”,不带小数。我猜DB列中的11.5可能存储为11.499999999~因此11.499999999~*1.15将是13.2249999999~因此四舍五入(13.22499999999~,2)将得到13.22。这取决于列类型。谢谢,使用十进制是正确的,我会记住这一点future@ipronet如果答案有帮助,也请标出。谢谢大家!@shadyyx那么什么时候会使用float和double,因为它们的存储方式不同?