用于存储货币价值的数字与实数数据类型

时间:2018-05-08 22:21:35

标签: postgresql types

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个小数位,我认为这就是我真正需要的。

我离开这里的基础,是否有可能通过使用真正的10,2数据类型得到上述比较的错误答案?

我也欢迎使用数字数据类型的任何其他评论,无论是赞成还是反对。

提前致谢。

2 个答案:

答案 0 :(得分:1)

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

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

Floating point inaccuracy examples

答案 1 :(得分:0)

让我们从上面的模式开始,看看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)

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

我的下一个问题是:如果您的应用程序扩展,并且不仅仅是" avg"计算 - 您是否需要再次将数据类型设置为数字?