为什么在财务计算中使用十进制浮点数,而它有舍入误差 我目前正在使用C++进行股票市场相关的项目,涉及到很多浮动类型,如价格和指数。

为什么在财务计算中使用十进制浮点数,而它有舍入误差 我目前正在使用C++进行股票市场相关的项目,涉及到很多浮动类型,如价格和指数。,c++,floating-point,bigdecimal,C++,Floating Point,Bigdecimal,我读过很多书,说你应该在货币相关的算术中使用十进制浮点数。 据我所知,浮点和十进制浮点的区别在于指数部分的解释基数,浮点使用2作为基数,十进制浮点使用10。当使用十进制浮点数时,仍然存在舍入误差,您仍然无法表示1/3(如果我错了,请纠正我),我猜很有可能将某人的帐户余额乘以30%,然后出现舍入误差,再进行一些计算后,舍入误差可能会传播得更严重。除了更大的数字范围之外,为什么我应该在金融算术中使用十进制浮点?根据您执行的金融交易,舍入错误可能是不可避免的。如果一件商品的价格为1.50美元,加上7

我读过很多书,说你应该在货币相关的算术中使用十进制浮点数。


据我所知,浮点和十进制浮点的区别在于指数部分的解释基数,浮点使用2作为基数,十进制浮点使用10。当使用十进制浮点数时,仍然存在舍入误差,您仍然无法表示1/3(如果我错了,请纠正我),我猜很有可能将某人的帐户余额乘以30%,然后出现舍入误差,再进行一些计算后,舍入误差可能会传播得更严重。除了更大的数字范围之外,为什么我应该在金融算术中使用十进制浮点?

根据您执行的金融交易,舍入错误可能是不可避免的。如果一件商品的价格为1.50美元,加上7%的销售税,你将不会被收取1.605美元;您支付的价格为1.60美元或1.61美元。(理论上,美国货币单位包括“密耳”,即千分之一美元,但最小面额的硬币是0.01美元,几乎所有交易都四舍五入到最接近的美分。)

如果你做的是简单的计算(只需加减数量并乘以整数),所有的结果都是以美分为单位的整数。如果使用二进制浮点表示美元数,大多数金额将无法表示;应产生0.01美元的计算可能产生0.010000000000000000208166817117216851329430937776702880859375美元

您可以通过使用整数来表示美分数(或者,如果语言支持,则等效地使用定点)或使用可以精确表示0.01的十进制浮点来避免该问题

但对于更复杂的操作,比如计算7%的销售税,将一笔钱分成3等份,或者特别是复利,仍然会有一些结果无法精确表示,除非你使用像这样的任意精度包

据我所知,有法律法规明确规定了如何解决舍入误差。如果你对1.50美元征收7%的销售税,你就不能在1.60美元和1.61美元之间合法选择;法律准确地告诉你哪一个在法律上是正确的

如果你正在编写供其他人使用的金融软件,你需要确切地了解法规是怎么规定的。一旦您知道了这一点,您就可以确定什么样的表示法(整数、定点、十进制浮点或任何形式)可以最好地用于获得法律要求的结果


(免责声明:我不知道这些规定实际上是怎么说的。)

至少在美国,大多数金融类公司都被要求使用十进制数学。从IBM360时代起,大型机就可以对压缩十进制的可变长度字符串执行数学运算。通常使用某种形式的定点数字,小数点后有一组数字。像Cobol这样的高级语言支持压缩(或非压缩)十进制数。在IBM大型机的情况下,有许多遗留的汇编代码与Cobol代码一起使用,部分原因是某些类型的数据库曾经通过汇编中的宏(现在称为HLASM-高级汇编)进行访问。

因为不能用二进制表示0.01。注:在0.1、0.2、0.3。。。,0.9只有0.5是一个精确的二进制浮点数,而所有的都是精确的十进制浮点数。你能做的最好的事情是使用纯整数算法:不要用美元计算,而是用美分(或者十分之一美分,如果你的帐户在该精度内的话)。这也可能存在效率问题。大多数浮点值存储在3个部分中。这三个片段必须被提取、加工,然后再重新组合。与整数相比,这是两个额外的运算。整数没有打包问题。FWIW,取十进制货币值的30%不会有任何舍入问题。货币价值不会深入到最底层,小数可以准确地表示百分比。我在想象一个数百万美元的诉讼,因为一个程序错误地将发票四舍五入到1.61美元,而不是1.60美元。@Mysticial:我在想象一个数百万美元的诉讼,因为一个程序错误地将发票四舍五入到1.61美元,而不是16亿美元。