kan*_*008 184
这是我怀疑时发现的.
mysql> create table numbers (a decimal(10,2), b float);
mysql> insert into numbers values (100, 100);
mysql> select @a := (a/3), @b := (b/3), @a * 3, @b * 3 from numbers \G
*************************** 1. row ***************************
  @a := (a/3): 33.333333333
  @b := (b/3): 33.333333333333
@a + @a + @a: 99.999999999000000000000000000000
@b + @b + @b: 100
十进制确实完成了对这种情况应该做的事情,它截断了其余部分,从而失去了1/3部分.
因此,对于总和,小数点更好,但对于除法,浮点数更好,当然还有一些点.我的意思是,使用DECIMAL不会以任何方式为您提供"失败证明算术".
希望这可以帮助.
Mic*_*tta 76
大多数环境中的"浮点"是二进制浮点类型.它可以准确地存储base-2值(到某个点),但不能准确存储许多base-10(十进制)值.浮子最适合科学计算.它们不适合大多数面向商业的数学运算,不合适地使用花车会让你感到厌烦.许多十进制值无法在base-2中精确表示.0.1例如,你不能看到像这样的奇怪结果1.0 - 0.1 = 0.8999999.
小数存储基数为10的数字.对于大多数商业数学而言,十进制是一个很好的类型(但任何内置的"货币"类型更适合于财务计算),其中值的范围超过整数类型提供的值,并且需要小数值.顾名思义,小数是为基数10设计的 - 它们可以准确地存储十进制值(再次,到某一点).
use*_*100 19
MySQL最近改变了他们存储DECIMAL类型的方式.在过去,他们为每个数字存储字符(或nybbles),包括数字的ASCII(或nybble)表示 - vs - 二进制补码整数或其衍生物.
DECIMAL的当前存储格式是一系列1,2,3或4字节整数,其位被连接以创建带有隐含小数点的二进制补码数,由您定义,并在您声明时存储在DB模式中列,并指定它的DECIMAL大小和小数点位置.
举例来说,如果你采用32位int,你可以存储0 - 4,294,967,295之间的任何数字.这只会可靠地覆盖999,999,999,所以如果你扔出2位并使用(1 << 30 -1)你就什么也不放弃.仅使用4个字节覆盖所有9位数字比使用4个ASCII字符或8个nybble数字覆盖32位中的4位数字更有效.(一个nybble是4位,允许值0-15,超过0-9所需的值,但你不能通过转到3位来消除这种浪费,因为它只涵盖0-7的值)
MySQL在线文档中使用的示例使用DECIMAL(18,9)作为示例.这比隐含小数点前面的9位数字和9位数字要短,如上所述,需要以下存储空间.
18个8位字符:144位
作为18个4位nybbles:72位
作为2个32位整数:64位
目前DECIMAL支持最多65位,如DECIMAL(M,D),其中M允许的最大值为65,D允许的最大值为30.
为了不一次要求9位数的块,小于32位的整数用于使用1,2和3字节整数来添加数字.出于某种原因,无视逻辑,使用了签名而不是无符号的int,并且这样做,1位被抛出,从而产生以下存储能力.对于1,2和4字节的整数,丢失的位无关紧要,但对于3字节的int来说,这是一场灾难,因为整个数字由于丢失了这一位而丢失.
使用7位int:0 - 99
使用15位int:0 - 9,999
使用23位int:0 - 999,999(0 - 9,999,999,带有24位int)
1,2,3和4字节整数连接在一起形成"位池"DECIMAL用于将数字精确地表示为二进制补码整数.小数点未存储,暗示.
这意味着数据库引擎不需要ASCII到int转换就可以将"数字"转换为CPU识别为数字的内容.没有舍入,没有转换错误,它是CPU可以操作的实数.
对这个任意大整数的计算必须在软件中完成,因为这种数字没有硬件支持,但这些库非常陈旧且经过高度优化,已在50年前编写,以支持IBM 370 Fortran任意精度浮点数据.它们仍然比使用CPU整数硬件完成的固定大小整数代数慢,或者在FPU上进行浮点计算.
就存储效率而言,因为float的指数附加到每个浮点数,隐含地指定小数点的位置,所以它是大量冗余的,因此对DB工作来说效率低.在数据库中,您已经知道小数点的位置在前面,并且表中具有DECIMAL列值的每一行只需要查看该小数点的放置位置的唯一规范,存储在模式中作为DECIMAL(M,D)的参数作为M和D值的含义.
这里发现的关于哪种格式用于各种应用程序的许多评论是正确的,所以我不会强调这一点.我花时间在这里写这篇文章,因为无论是谁维护链接的MySQL在线文档都不理解上述任何内容,并且经过多次令人沮丧的尝试向他们解释它后,我放弃了.很好地表明他们对所写内容的理解程度有多差,这是对主题的非常混乱和难以理解的表现.
最后,如果您需要高精度浮点计算,过去20年浮点代码已经取得了巨大进步,96位和四倍精度浮点数的硬件支持即将到来,但是如果存储值的操作很重要,那么有很好的任意精度库.
Sin*_*ion 12
不仅仅是特定于MySQL,float和decimal类型之间的区别在于它们代表小数值的方式.浮点类型表示二进制的分数,它只能表示值{m*2^n | m, n Integers}.诸如1/5之类的值无法精确表示(没有舍入误差).十进制数字同样受限,但代表数字{m*10^n | m, n Integers}.小数仍然不能代表1/3之类的数字,但在许多常见领域(例如金融)中通常会出现这样的情况,即期望是某些小数部分总是可以在不损失保真度的情况下表达.由于十进制数可以表示像$0.20(美元的五分之一)的值,因此在这些情况下是优选的.
小智 6
我发现这很有用:
通常,浮点值适用于科学计算,但不应用于财务/货币值。对于面向商业的数学,请始终使用十进制。
来源:http : //code.rohitink.com/2013/06/12/mysql-integer-float-decimal-data-types-differences/
mysql> CREATE TABLE num(id int ,fl float,dc dec(5,2));
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO num VALUES(1,13.75,13.75);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO num VALUES(2,13.15,13.15);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM num WHERE fl = 13.15;
Empty set (0.00 sec)
mysql> SELECT * FROM num WHERE dc = 13.15;
+------+-------+-------+
| id   | fl    | dc    |
+------+-------+-------+
|    2 | 13.15 | 13.15 |
+------+-------+-------+
1 row in set (0.00 sec)
mysql> SELECT SUM(fl) ,SUM(dc)  FROM num;
+--------------------+---------+
| SUM(fl)            | SUM(dc) |
+--------------------+---------+
| 26.899999618530273 |   26.90 |
+--------------------+---------+
1 row in set (0.00 sec)
mysql> SELECT * FROM num WHERE ABS(fl -  13.15)<0.01;
+------+-------+-------+
| id   | fl    | dc    |
+------+-------+-------+
|    2 | 13.15 | 13.15 |
+------+-------+-------+
1 row in set (0.00 sec)