【问题标题】:Numeric vs Real Datypes for Storing Monetary Values用于存储货币价值的数字与实数数据类型
【发布时间】:2018-05-09 22:45:55
【问题描述】:

a question about a good schema for stock data 的回答推荐了这个架构:

 Symbol -  char 6
 Date -  date
 Time -  time
 Open -  decimal 18, 4
 High -  decimal 18, 4
 Low -  decimal 18, 4
 Close -  decimal 18, 4
 Volume -  int

此外,Postgres 文档说:

“如果您需要精确的存储和计算(例如货币金额),请使用数字类型(而非浮点类型)。”

我是 SQL 的新手,我希望这不是一个非常幼稚的问题。我想知道使用数字数据类型(尤其是 18,4)的必要性——这对我来说似乎有点矫枉过正。而“精确”并不是我真正要指定的东西,如果精确意味着纠正到小数点后 12 位。

我正在考虑使用真正的 10,2 作为货币列。这是我的理由。

典型的计算可能会将股票价格(2 位小数)与移动平均线(可能有多个小数位)进行比较,以确定哪个更大。我的理解是显示的平均值(以及任何计算结果)将四舍五入到小数点后 2 位,但计算将使用存储的内部数字的更高精度来执行。

所以这样的计算至少可以精确到小数点后 2 位,我认为这确实是我所需要的。

我在这里是不是有点离谱,使用真正的 10,2 数据类型是否可能对上述比较得出错误的答案?

我也欢迎任何其他 cmets,赞成或反对,关于使用数字数据类型。

提前致谢。

【问题讨论】:

标签: postgresql types


【解决方案1】:

浮点变量容易受到浮点错误的影响。因此,如果准确性很重要(只要涉及金钱),始终建议使用数字类型。

https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems

Floating point inaccuracy examples

【讨论】:

    【解决方案2】:

    让我们从上面的架构开始,看看 18,4 在浮点数中的样子:

    select '12345678901234.5678'::float4;
      float4    
    -------------
     1.23457e+13
    (1 row)
    
    select '12345678901234.5678'::double precision;
      float8      
    ------------------
     12345678901234.6
    (1 row)
    

    因此,14 个数字(小数点前)将始终对您的数字进行四舍五入,并且您存储四舍五入的值(因此是错误的)。

    还有你关于四舍五入到小数点后两位的假设——这个假设来自哪里?

    select '1.2345678'::float4;
     float4  
    ---------
     1.23457
    (1 row)
    

    因此,到目前为止,您提出了许多假设和捷径,但没有说明为什么要使用浮点数而不是数字。你有什么令人信服的理由?只是节省一些字节?

    我的下一个问题是:如果您的应用程序扩展,并且不仅仅是“平均”计算 - 您是否需要再次将数据类型更改为数字?

    【讨论】:

      猜你喜欢
      • 2012-10-13
      • 2017-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-11
      • 2016-06-25
      相关资源
      最近更新 更多