我们正在用VB.NET和SQL Server重写我们的旧会计系统.我们引入了一个新的.NET/SQL程序员团队来进行重写.大多数系统已经使用Floats完成了Dollar数量.我编程的遗留系统语言没有Float,所以我可能会使用Decimal.
你有什么建议?
Float或Decimal数据类型应该用于美元金额吗?
两者的优点和缺点有哪些?
在我们的日常scrum中提到的一个骗局是,当你计算一个返回超过两个小数位的结果的金额时,你必须要小心.听起来你必须将金额四舍五入到小数点后两位.
另一个Con是所有显示和打印金额必须有一个显示两个小数位的格式声明.我注意到有几次没有这样做,金额看起来不正确.(即10.2或10.2546)
专家是Float只占用磁盘上的8个字节,其中Decimal占用9个字节(十进制12,2)
Float或Decimal数据类型应该用于美元金额吗?
答案很简单.永远不要漂浮.永远不会!
浮点数是根据IEEE 754始终二进制,只有新标准IEEE 754R定义的十进制格式.许多小数二进制部分永远不能等于精确的十进制表示.
任何二进制数都可以写成m/2^n
(m
,n
正整数),任何十进制数m/(2^n*5^n)
.
由于二进制文件缺少素数factor 5
,所有二进制数可以用小数精确表示,但反之亦然.
0.3 = 3/(2^1 * 5^1) = 0.3 0.3 = [0.25/0.5] [0.25/0.375] [0.25/3.125] [0.2825/3.125] 1/4 1/8 1/16 1/32
因此,您最终会得到一个高于或低于给定十进制数的数字.总是.
为什么这么重要?四舍五入.
正常舍入表示0..4向下,5..9向上.因此,它确实重要,如果结果为0.049999999999
....或者0.0500000000
......你可能知道,这意味着5%,但对计算机不知道和轮0.4999
...向下(错)和0.5000
...起来(右).
鉴于浮点计算的结果总是包含小的错误项,因此决定是纯粹的运气.如果你想要使用二进制数进行十进制舍入到偶数处理,那就无望了.
不相信?你坚持认为在你的帐户系统中一切都很好吗?
资产和负债相等?好的,然后获取每个条目的每个给定格式化的数字,解析它们并用独立的十进制系统求和它们!将其与格式化的总和进行比较.
糟糕,有些不对劲,不是吗?
对于那个计算,需要极高的准确性和保真度(我们使用Oracle的FLOAT),因此我们可以记录得到的"十分之一便士".
无助于解决此错误.因为所有人都自动认为计算机总和正确,所以几乎没有人独立检查.
这张照片答案:
这是另一种情况:来自北安普顿的人得到一封信,说如果他没有支付零美元和零美分就会被扣押!
首先,您应该阅读每个计算机科学家应该知道的关于浮点运算的内容.那么你应该考虑使用某种类型的定点/任意精度数字包(例如java BigNum,python十进制模块),否则你将陷入一个受伤的世界.然后弄清楚是否使用本机SQL十进制类型就足够了.
浮点/双打存在(ed)以暴露快速x87 fp,现在已经过时了.如果您关心计算的准确性和/或不完全补偿其限制,请不要使用它们.
正如另一个警告,SQL Server和.Net框架使用不同的默认算法进行舍入.请务必查看Math.Round()中的MidPointRounding参数..Net框架默认使用Bankers算法,SQL Server使用Symmetric Algorithmic Rounding.在这里查看维基百科的文章
问问你的会计师!他们会对你使用漂浮物皱眉.就像之前发布的一些,如果您不关心准确性,请仅使用float.虽然在谈到金钱时我总是反对它.
在会计软件中不可接受浮动.使用带小数点后4位的小数.
浮点有意想不到的无理数.
例如,你不能存储1/3作为小数,它将是0.3333333333 ......(依此类推)
浮点数实际上存储为二进制值和2指数幂.
所以1.5被存储为3 x 2到-1(或3/2)
使用这些base-2指数会创建一些奇怪的无理数,例如:
将1.1转换为浮点数然后再将其转换回来,结果如下:1.0999999999989
这是因为1.1的二进制表示实际上是154811237190861 x 2 ^ -47,超过双倍可以处理.
更多关于我的博客上的这个问题,但基本上,对于存储,你最好用小数.
在Microsoft SQL服务器上,您具有money
数据类型 - 这通常最适合财务存储.精确到4位小数.
对于计算,你有更多的问题 - 不准确性是一小部分,但把它放入一个幂函数,它很快就会变得很重要.
但是小数对于任何类型的数学都不是很好 - 例如,没有对十进制幂的原生支持.
使用SQL Server的十进制类型.
不要用钱或漂浮.
money使用4位小数,比使用decimal更快但是有一些明显的和一些不那么明显的舍入问题(见这个连接问题)
我推荐的是使用64位整数来存储整个东西.
这里有点背景......
没有数字系统可以准确处理所有实数.所有这些都有其局限性,这包括标准IEEE浮点和带符号小数.每个位使用的IEEE浮点更准确,但这并不重要.
财务数据基于几个世纪的纸笔练习以及相关的惯例.它们相当准确,但更重要的是,它们是可重复的.使用各种数字和费率的两名会计师应该提出相同的数字.任何差异的余地都是欺诈的余地.
因此,对于财务计算,正确答案是与擅长算术的注册会计师给出相同答案的答案.这是十进制算术,而不是IEEE浮点.