【问题标题】:When to use float vs decimal何时使用浮点数与小数
【发布时间】:2020-05-08 02:17:38
【问题描述】:

我正在构建这个 API,数据库将存储代表以下之一的值:

  • 百分比
  • 平均

老实说,我不知道如何用数字表示范围在 0 到 100% 之间的东西。应该是

  • 0.00 - 1.00
  • 0.00 - 100.00
  • 我不知道的任何其他替代方法

对此有明确的选择吗?一种在数据库上表示从 0% 到 100% 的全局方式?更进一步,它的正确类型是什么,浮点数还是小数?

谢谢。

【问题讨论】:

  • 数字可以以多种方式存储。使用 0-100 或使用 0-1 存储百分比本质上没有任何问题。重要的是你需要对数字做什么,你需要什么准确性等等。在给出一个好的答案之前,您必须解释更多的上下文。您是否需要存储可以用少量十进制数字精确表示的数字?如果你平均一些东西,你会得到像三分之一或七分之一这样的分数。你需要准确地存储这些吗?还是大约?大约多少?你会用它们做什么?
  • 如果值是 0.00 到 100.00,步长为 0.01,即 10001 个不同的值。只需使用 int 来表示 hundredths 或以 Permyriad 或‱为单位。
  • @chux-ReinstateMonica - 是的,“缩放整数”是可能的,但很笨拙。
  • @RickJames 也许吧。我没有发现缩放整数很困难。

标签: mysql sql types floating-point decimal


【解决方案1】:

我会采取相反的立场。

FLOAT 用于近似数字,例如百分比、平均值等。您应该在显示值时进行格式化,无论是在应用程序代码中还是使用 MySQL 的 FORMAT() 函数。

永远不要测试float_value = 1.3;失败的原因有很多。

DECIMAL 应该用于货币价值。 DECIMAL 在需要将值四舍五入为美元/美分/欧元/等时避免第二次四舍五入。会计师不喜欢零碎的美分。

MySQL 对DECIMAL 的实现允许65 位有效数字; FLOAT 大约是 7,DOUBLE 大约是 16。7 通常对于传感器和科学计算来说已经足够了。

至于“百分比”——有时我使用TINYINT UNSIGNED,当我只想消耗1个字节的存储空间并且不需要太多精度时;有时我使用了FLOAT(4 个字节)。没有专门针对百分比调整的数据类型。 (另请注意,DECIMAL(2,0) 不能保存值 100,因此从技术上讲,您需要 DECIMAL(3,0)。)

或者有时我使用了一个值介于 0 和 1 之间的 FLOAT。但是我需要确保在显示“百分比”之前乘以 100。

更多

“百分比、平均值、比率”这三个都闻起来像浮点数,所以这将是我的首选。

决定数据类型的一个标准...该值将存在多少个副本?

如果您有一个十亿行的表,其中有一列表示百分比,请考虑 TINYINT 将占用 1 个字节(总共 1GB),但 FLOAT 将占用 4 个字节(总共 4GB)。 OTOH,大多数应用程序没有那么多行,所以这可能不相关。

作为“一般”规则,“精确”值应使用某种形式的INTDECIMAL。不精确的东西(科学计算、平方根、除法等)应该使用FLOAT(或DOUBLE)。

此外,输出的格式通常应该留给应用程序前端。也就是说,即使“平均值”可能计算为“14.6666666...”,显示器也应该显示类似“14.7”的内容;这对人类更友好。同时,您有基础值来决定“15”或“14.667”是更可取的输出格式。

“0.00 - 100.00”范围可以使用FLOAT并使用输出格式DECIMAL(5,2)(3 个字节)预先确定您将始终想要指定的精度

【讨论】:

    【解决方案2】:

    在 tsql 中: 浮点数,0.0 存储为 0,不需要在小数点后定义,例如你不需要写 Float(4,2)。 十进制,0.0 存储为 0.0,它可以选择定义为小数(4,2),我建议 0.00-1.00,通过这样做,您可以计算该百分比的值而无需乘以 100,如果您报告则设置数据类型该列的百分比为 MS Excel 和其他平台视图(如 0.5 -> 50%)。

    【讨论】:

      【解决方案3】:
      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
      
      *********************************************************************
      
      @a := (a/3): 33.333333333
      @b := (b/3): 33.333333333333
      @a + @a + @a: 99.999999999000000000000000000000
      @b + @b + @b: 100
      

      在这种情况下,小数点做了应该做的事情,它 截断其余部分,从而丢失 1/3 部分。

      所以对于总和,小数更好,但对于除法,浮点数是 更好,在某种程度上,当然。我的意思是,使用 DECIMAL 不会给出 你以任何方式“防错算术”。

      我希望这会有所帮助。

      【讨论】:

        【解决方案4】:

        十进制: 在金融应用中,最好使用小数类型,因为它可以为您提供高水平的准确性并且易于避免舍入错误

        双: Double 类型可能是实际值最常用的数据类型,除了处理钱。

        浮动: 它主要用于图形库,因为对处理能力的要求非常高,还使用了可以忍受舍入误差的情况。

        参考:http://net-informations.com/q/faq/float.html

        【讨论】:

          【解决方案5】:

          我建议使用decimal(5,2),如果您要以与显示它相同的方式存储它,因为decimal 是为了保持精确的精度。 (见https://dev.mysql.com/doc/refman/8.0/en/fixed-point-types.html

          由于浮点值是近似值而不是存储为精确值,因此在比较中尝试将它们视为精确值可能会导致问题。它们还受制于平台或实现依赖项。

          (https://dev.mysql.com/doc/refman/8.0/en/floating-point-types.html)

          SQL 语句中写入的浮点值可能与内部表示的值不同。

          对于 DECIMAL 列,MySQL 执行精度为 65 位小数的操作,这应该可以解决最常见的不准确问题。

          https://dev.mysql.com/doc/refman/8.0/en/problems-with-float.html

          【讨论】:

            【解决方案6】:

            浮点数和小数点的区别在于精度。 Decimal 可以 100% 准确地表示小数格式精度范围内的任何数字,而 Float 不能准确地表示所有数字。

            使用十进制表示例如财务相关价值和使用浮动,例如图形相关值

            【讨论】:

              【解决方案7】:

              我通常建议不要使用float。浮点数确实表示以 2 为基数的数字,这会导致一些(精确)数字在运算或比较中被舍入,因为它们无法准确地以 2 为基数存储。这可能会导致出人意料的行为。

              考虑the following example

              create table t (num float);
              insert into t values(1.3);
              
              select * from t;
              
              | num |
              | --: |
              | 1.3 |
              
              select * from t where num = 1.3;
              
              | num |
              | --: |
              

              数字 1.3 的 Base-2 比较失败。这很棘手。

              相比之下,十进制可以准确表示其范围内的有限数。如果您在上面的示例中将float 更改为decimal(2, 1),您确实会得到预期的结果。

              【讨论】:

              • 这个答案在几个方面是错误的。 “相比之下,十进制的范围更小,但提供了该范围内有限数字的精确表示”是错误的:十进制并不完全表示⅓。 “一些(精确的、有限的)数字是四舍五入的”是不正确的;数字不是“四舍五入”。转换和其他操作可能会舍入。默认的舍入模式最常见的是四舍五入,而不是四舍五入。
              • 准确性问题不是由于“浮点数”,而仅仅是由于数值表示:所有有限数值表示的准确性有限:浮点数、定点数、整数、有理数、十进制、二进制,应有尽有。
              • 叹息。你修了什么?我的评论说答案是错误的,因为它说十进制提供了其范围内数字的精确表示,但实际上它没有提供 ⅓ 的精确表示。更改说“准确”而不是“精确”,但是为什么二进制浮点数不一样好 - 对于 ⅓ 都不精确,两者或都不准确,具体取决于您的准确阈值和精度他们有。问题表明将表示平均值,平均三件事会给你像⅓这样的数字。
              • 评论说round-to-nearest-ties-to-even是最常用的,但答案仍然是round-up。答案是比较可能会四舍五入,但比较是完美的:比较总是返回数学上正确的结果,没有四舍五入。 (一些编程语言可能会在比较之前转换操作数,但这些是单独的操作。)
              • 1/3 不能完全以二进制或十进制表示。 14.99 美元的 20% 折扣将需要舍入不存在的小数美分。
              猜你喜欢
              • 2021-09-26
              • 1970-01-01
              • 2022-01-23
              • 1970-01-01
              • 2011-11-23
              • 2011-04-15
              • 1970-01-01
              • 2012-07-21
              • 2017-03-22
              相关资源
              最近更新 更多