为了账号安全,请及时绑定邮箱和手机立即绑定

float和decimal数据类型之间的差异

float和decimal数据类型之间的差异

慕的地10843 2019-09-20 16:29:59
float和decimal数据类型之间的差异当我在MySQL中使用float和decimal数据类型时,它有什么不同?我什么时候应该使用哪个?
查看完整描述

3 回答

?
慕容708150

TA贡献1831条经验 获得超4个赞

这是我怀疑时发现的。


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不会以任何方式为您提供“失败证明算术”。


希望这可以帮助。


查看完整回答
反对 回复 2019-09-20
?
慕姐8265434

TA贡献1813条经验 获得超2个赞

大多数环境中的“浮点”是二进制浮点类型。它可以准确地存储base-2值(到某个点),但不能准确存储许多base-10(十进制)值。浮子最适合科学计算。它们适合大多数面向商业的数学运算,不合适地使用花车会让你感到困惑。许多十进制值无法在base-2中精确表示。0.1例如,你不能看到像这样的奇怪结果1.0 - 0.1 = 0.8999999

小数存储基数为10的数字。对于大多数商业数学而言,十进制是一个很好的类型(但任何内置的“货币”类型更适合于财务计算),其中值的范围超过整数类型提供的值,并且需要小数值。顾名思义,小数是为基数10设计的 - 它们可以准确地存储十进制值(再次,到某一点)。


查看完整回答
反对 回复 2019-09-20
?
Smart猫小萌

TA贡献1911条经验 获得超7个赞

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位和四倍精度浮点数的硬件支持即将到来,但是如果存储值的操作很重要,那么有很好的任意精度库。


查看完整回答
反对 回复 2019-09-20
  • 3 回答
  • 0 关注
  • 894 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信