浮点数的比较和运算会损失精度,对于涉及金钱的存储与运算,需要高精度的存储与计算。

    Mysql中,float为单精度浮点型,double为双精度浮点型,这两种在计算时都会存在失真的问题,而decimal,则可以解决这样的问题,具体如下:

MySQL DECIMAL数据类型用于在数据库中存储精确的数值。我们经常将DECIMAL数据类型用于保留准确精确度的列,例如会计系统中的货币数据。

要定义数据类型为DECIMAL的列,请使用以下语法:

column_name  DECIMAL(P,D);
P
是表示有效数字数的精度。 P范围为1〜65。在上面的语法中:

  • D是表示小数点后的位数。 D的范围是0~30。MySQL要求D小于或等于(<=)P

DECIMAL(P,D)表示列可以存储D位小数的P位数。十进制列的实际范围取决于精度和刻度。

与INT数据类型一样,DECIMAL类型也具有UNSIGNEDZEROFILL属性。 如果使用UNSIGNED属性,则DECIMAL UNSIGNED的列将不接受负值。

如果使用ZEROFILL,MySQL将把显示值填充到0以显示由列定义指定的宽度。 另外,如果我们对DECIMAL列使用ZERO FILL,MySQL将自动将UNSIGNED属性添加到列。



MySQL DECIMAL存储

    MySQL分别为整数和小数部分分配存储空间。 MySQL使用二进制格式存储DECIMAL值。它将9位数字包装成4个字节。

对于每个部分,需要4个字节来存储9位数的每个倍数。剩余数字所需的存储如下表所示:

剩余数字


0

0

1–2

1

3–4

2

5–6

3

7-9

4

例如,DECIMAL(19,9)对于小数部分具有9位数字,对于整数部分具有19-9位= 10位数字,小数部分需要4个字节。 整数部分对于前9位数字需要4个字节,1个剩余字节需要1个字节。DECIMAL(19,9)列总共需要9个字节。(当做字符串存储)

 

PHP 对高精度计算的方法:

bc数学函数,提供了高精度计算的方法。

bc是Binary Calculator的缩写。bc*函数的参数都是操作数加上一个可选的 [int scale],比如string bcadd(string $left_operand, string $right_operand[, int $scale]),如果scale没有提供,就用bcscale的缺省值。这里大数直接用一个由0-9组成的string表示,计算结果返回的也是一个 string。

bcadd — 将两个高精度数字相加 
bccomp — 比较两个高精度数字,返回-1, 0, 1 
bcdiv — 将两个高精度数字相除 
bcmod — 求高精度数字余数 
bcmul — 将两个高精度数字相乘 
bcpow — 求高精度数字乘方 
bcpowmod — 求高精度数字乘方求模,数论里非常常用 
bcscale — 配置默认小数点位数,相当于就是Linux bc中的”scale=” 
bcsqrt — 求高精度数字平方根 
bcsub — 将两个高精度数字相减