从字面上看,我只是在做两个浮点数的乘法。为什么这些陈述会产生不同的结果?我什至应该使用花车吗?
500,000.00 * 0.001660 = 830
从字面上看,我只是在做两个浮点数的乘法。为什么这些陈述会产生不同的结果?我什至应该使用花车吗?
500,000.00 * 0.001660 = 830
为什么这些陈述会产生不同的结果?
因为浮点运算并不精确,而且显然您打印乘数的精度不够(即具有足够数量的十进制数字)。它不是看起来很圆的.00166
东西。 0.00166
我什至应该使用花车吗?
不。对于金钱,使用整数并将它们视为定点有理数。(它们仍然不准确,但明显更好,更不容易出错。)
你没有展示你是如何初始化periodicInterest
的,大概你认为你将它设置为0.00166
,但实际上你的输出中的错误足够大,你一定没有明确地将它初始化为periodicInterest = 0.00166
。它必须更接近,并且和0.00165975
之间的差异绝对足够大,而不仅仅是单个浮点舍入误差。0.00166
0.00165975
假设您正在处理货币数量,您应该使用NSDecimalNumber
or NSDecimal
。
使用的一个不明显的好处NSDecimalNumber
是它适用于NSNumberFormatter
,因此您可以让 Apple 负责为各种外国语言环境设置货币格式。
回应评论:
“<code>periodicInterest 显然不是货币数量”和“十进制除以 12 时不会比二进制更容易出错”——对于不精确的数量,我可以考虑两个问题:
一个问题是使用足够的精度来给出准确的结果。 NSDecimalNumber
是一个浮点数,精度为 38 位,指数范围为 -128…127。这是 IEEE 'double' 可以存储的十进制位数的两倍多。指数范围小于 a double
,但这在金融计算中不太重要。所以NSDecimalNumber
s 肯定会导致比float
s 或double
s 更小的误差,即使它们都不能精确地存储 1/12。
另一个问题是与其他系统计算的结果相匹配,例如您的银行、经纪人或纽约证券交易所。在这种情况下,您需要弄清楚其他系统如何存储数字并使用它们进行计算。如果其他系统使用十进制格式(可能在金融领域),那么NSDecimalNumber
可能会有用。
“使用原始类型进行浮点运算不是更有效吗,特别是实时数以千计。” 原始类型的算术比 s 的算术快得多NSDecimalNumber
。我没有测量它,但 100 倍不会让我感到惊讶。
你必须在你的要求之间取得平衡。如果小数精度是最重要的(就像在金融编程中经常出现的那样),您必须牺牲性能来换取准确性。如果小数精度不是那么重要,您可以仔细考虑使用原始类型,但您应该注意您要牺牲的精度。即使这样,a 的大小float
也非常小(通常只有 7 个有效十进制数字),您可能应该使用double
(至少 15 个,通常是 16 个有效十进制数字)。
如果您需要以真正的十进制精度每秒执行数百万次算术运算,则可以使用double
s 来完成,如果您是一位 IEEE 754 专家,能够分析您的代码以找出引入错误的位置以及如何消除它们. 很少有人具备这种水平的专业知识。(我没有声称。)您还必须了解您的编译器如何将您的 Objective-C 代码转换为机器指令。
无论如何,也许您只是在编写一个休闲应用程序来计算净现值或未来值的粗略估计。在这种情况下, usingdouble
可能就足够了,但 usingNSDecimalNumber
也可能足够快。如果不了解您正在编写的应用程序的更多信息,我无法给您更具体的建议。