我正在使用十进制列来存储数据库中的货币值,而今天我想知道要使用的精度和规模.
因为据说固定宽度的char列效率更高,我认为对于十进制列也是如此.是吗?
我应该使用什么精度和规模?我正在考虑精确24/8.这有点矫枉过正,还不够或没问题?
这就是我决定做的事情:
将转换率(适用时)存储在事务表本身中,作为float
将货币存储在帐户表中
交易金额为a DECIMAL(19,4)
使用转换率的所有计算都将由我的应用程序处理,因此我可以控制舍入问题
我不认为转换率的浮点数是一个问题,因为它主要用于参考,我将把它转换为十进制.
谢谢大家的宝贵意见.
如果你正在寻找DECIMAL(19, 4)
一个通用的,我建议是一个受欢迎的选择(快速谷歌承担这一点).我认为这源于旧的VBA/Access/Jet Currency数据类型,是该语言中的第一个定点十进制类型; Decimal
在VB6/VBA6/Jet 4.0中只有'版本1.0'样式(即未完全实现).
存储固定点十进制值的经验法则是存储至少比您实际需要的小数位数多一个以允许舍入.Currency
将前端的旧类型映射到后端的DECIMAL(19, 4)
类型的原因之一是Currency
银行家本质上是DECIMAL(p, s)
圆形的,而截断则是圆形的.
存储中的额外小数位DECIMAL
允许实现自定义舍入算法而不是采用供应商的默认值(并且银行家的舍入是令人震惊的,至少可以说,设计师期望所有以.5结尾的值从零开始舍入) .
是的,DECIMAL(24, 8)
听起来有点矫枉过正.大多数货币都是小数点后四位或五位.我知道需要小数为8(或更多)的情况,但这是"正常"货币金额(比如说小数点后四位)的情况,这意味着小数精度应相应降低(也要考虑在这种情况下的浮点类型).现在没有人有这么多钱要求小数精度为24 :)
然而,一些研究可能是有序的,而不是一刀切的方法.向您的设计师或领域专家咨询可能适用的会计规则:GAAP,EU等.我模糊地回顾一些欧盟国内转移,其中有明确的规则,用于舍入到小数点后五位,因此DECIMAL(p, 6)
用于存储.会计师通常似乎偏爱四位小数.
PS避免使用SQL Server的MONEY
数据类型,因为它在舍入时存在严重的准确性问题,以及可移植性等其他考虑因素.请参阅Aaron Bertrand的博客.
微软和语言设计师选择了银行家的四舍五入,因为硬件设计师选择了它[引用?].例如,它被载入电气和电子工程师协会(IEEE)标准.硬件设计师选择它是因为数学家更喜欢它.见维基百科 ; 换句话说:1906年版的"概率论和错误论"称这是"计算机的规则"("计算机"意味着执行计算的人).
我们最近实现了一个系统,它需要处理多种货币的价值并在它们之间进行转换,并且很难找到一些东西.
永远不要使用浮动点数来赚钱
浮点运算引入了一些不准确的问题,直到他们搞砸了一些东西才会被注意到.所有值都应该存储为整数或固定小数类型,如果您选择使用固定小数类型,那么请确保您确切了解该类型的内容(即内部使用整数或浮点数)类型).
当您需要进行计算或转换时:
将值转换为浮点
计算新值
将数字四舍五入并将其转换回整数
在步骤3中将浮点数转换回整数时,不要只是强制转换它 - 使用数学函数先将其舍入.这通常是round
,但在特殊情况下,它可能是floor
或ceil
.了解差异并谨慎选择.
将值的类型与值一起存储
如果您只处理一种货币,这对您来说可能不那么重要,但对我们来说处理多种货币非常重要.我们使用3字符代码表示货币,例如美元,英镑,日元,欧元等.
根据具体情况,存储可能也会有所帮助:
税号是税前还是税后(以及税率是多少)
该数字是否是转换的结果(以及转换后的数字)
知道你正在处理的数字的准确性界限
对于实际值,您希望与货币的最小单位一样精确.这意味着您没有小于1美分,1美分,日元,分钟等的值.不要存储比无理由更高精度的值.
在内部,您可以选择处理较小的值,在这种情况下,这是一种不同类型的货币值.确保您的代码知道哪些是哪个,哪些不会混淆.即使在这里也避免使用浮点值.
将所有这些规则加在一起,我们决定了以下规则.在运行代码中,货币使用整数存储为最小单位.
class Currency { String code; // eg "USD" int value; // eg 2500 boolean converted; } class Price { Currency grossValue; Currency netValue; Tax taxRate; }
在数据库中,值以下列格式存储为字符串:
USD:2500
它存储了25.00美元的价值.我们能够做到这一点只是因为处理货币的代码不需要在数据库层本身内,因此所有值都可以先转换为内存.毫无疑问,其他情况也适用于其他解决方案.
如果我之前没有说清楚,请不要使用浮动!