我试图使用NSDecimalRound(...
将Decimal
值舍入。在大多数情况下,它的行为符合我的期望,但有时它会返回一个让我惊讶的值。在下面的例子中,第一个计算完成了我所期望的,即scale
为4
,将2341.2143
舍入到2341.2143
(即相同的值)。第二次计算是相同的,除了现在被舍入的值是2341.2142
(注意最后一位数字是2而不是3),这次返回的值是2341.2141
,而我期望的值是2341.2142
。在2341.2146
中也发现了类似的行为,当四舍五入到4 d.p时,它变成了2341.2145
。有人能解释为什么会发生这种情况吗?
// Working as expected... ////////////
var unrounded: Decimal = 2341.2143
var rounded = Decimal()
NSDecimalRound(&rounded, &unrounded, 4, .down)
print(rounded) // 2.2143
// A bit unexpected (to me at least) /////////
var unrounded: Decimal = 2341.2142
var rounded = Decimal()
NSDecimalRound(&rounded, &unrounded, 4, .down)
print(rounded) // 2.2141
问题来自于文字,它是Double
,必须转换为Decimal
。所以错误来自于转换:
var unrounded: Decimal = 2341.2143
// ^-- decimal var ^-- Double literal
如您所知,浮点编码容易出错。你可以在这里检查:
2341.2143 is encoded as 2341.21430000000009385985322296619415283203125
rounded down makes 2341.2143
2341.2142 is encoded as 2341.21419999999989158823154866695404052734375
rounded down makes 2341.2141
您需要初始化Decimal
以受益于更高的精度。不幸的是,这并不直观。例如,您可以使用以下命令,它的行为符合预期:
var unrounded3: Decimal = Decimal(sign:.plus, exponent:-4, significand:23412142)
var rounded3 = Decimal()
NSDecimalRound(&rounded3, &unrounded3, 4, .down)
print(rounded3)