NSDecimalNumber(x).intValue返回-2、0、15和199,具体取决于x中的小数位数(x = 199.999 ... 5) [英] NSDecimalNumber(x).intValue returns -2, 0, 15 and 199, depending on the amount of decimals in x (x = 199.999...5)

查看:86
本文介绍了NSDecimalNumber(x).intValue返回-2、0、15和199,具体取决于x中的小数位数(x = 199.999 ... 5)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们在业务逻辑中发现了一个有趣的案例,该案例完全破坏了我们的逻辑,并且我们不理解为什么NSDecimalNumberDecimal的行为方式如此.

We found an interesting case in our business logic that totally breaks our logic and we don't understand why NSDecimalNumber and Decimal behaves the way it does.

我的案件游乐场如下:

import Foundation

let pQuantity = Decimal(string: "0.2857142857142857")!
let pPrice = Decimal(string: "7.00000000000000035")!

let calced = NSDecimalNumber(decimal: pQuantity * pPrice * Decimal(integerLiteral: 100))   // 200
let decimal = calced.decimalValue                                                          // 199.9999999999999999999999999999995
let integer = calced.intValue                                                              // 0

NSDecimalNumber(decimal: Decimal(string: "199.9999999999999999999999999999995")!).intValue // 0
NSDecimalNumber(decimal: Decimal(string: "199.9999999999999995")!).intValue                // 199
NSDecimalNumber(decimal: Decimal(string: "199.99999999999999995")!).intValue               // 15
NSDecimalNumber(decimal: Decimal(string: "199.999999999999999995")!).intValue              // -2

如果您不想自己运行,则在上面的操场代码中,如果向右滚动,则可以看到返回值.

In the playground code above you can see the return value if you scroll to the right, if you don't want to run it yourselves.

在计算平均分配这些数量以产生美观价格时,我们需要暂时将原始十进制值,数量和价格转换为整数.但是,由于某种原因,由于转换的初始步骤失败,我们无法生成0而不是200(是的,当前代码将生成199,这是一个错误),因此我们无法这样做.

We need to convert our raw decimal values, quantity and price, to ints temporarily when calculating how much to evenly split these quantities to produce nice-looking prices. We can't however for some reason in this case as the initial step of conversion fails, producing a 0 instead of 200 (and yes, the current code would produce 199 which is a bug).

为什么NSDecimalNumber根据小数位数(从-2199)返回这些奇怪的值?

Why does the NSDecimalNumber return these weird values depending on the amount of decimals, ranging from -2 to 199?

我们的解决方案是在将内部计算放入NSDecimalNumber之前对其进行四舍五入,但是我们想知道开始的原因.是一个错误还是它是预期的,并且应该意识到它可能会发生?

Our solution would be to round the inner calculation before putting it into NSDecimalNumber, but we'd like to know the cause of this to begin with. Is it a bug or is it expected and one should be aware that it might happen?

推荐答案

这显然是基础错误,可能是

It's clearly a foundation bug, probably the one mentioned by Martin R in the comments.

我在Playground(Swift 5)中进行了实验,发现关于int32Value正常工作的bug的评论是正确的.

I experimented in Playground (Swift 5) and found that the comment on that bug that int32Value works correctly is true.

import Foundation

let pQuantity = Decimal(string: "0.2857142857142857")!
let pPrice = Decimal(string: "7.00000000000000035")!

let calced = NSDecimalNumber(decimal: pQuantity * pPrice * Decimal(integerLiteral: 100))   // 200
let decimal = calced.decimalValue                                                          // 199.9999999999999999999999999999995
let integer = calced.int32Value                                                              // 200

NSDecimalNumber(decimal: Decimal(string: "199.9999999999999999999999999999995")!).uint32Value // 200
NSDecimalNumber(decimal: Decimal(string: "199.9999999999999995")!).int32Value                // 200
NSDecimalNumber(decimal: Decimal(string: "199.99999999999999995")!).int32Value               // 200
NSDecimalNumber(decimal: Decimal(string: "199.999999999999999995")!).int32Value              // 200

此外,如您所见,uint32Value也可以正常工作.但是,这64位变体都不起作用.

Also, as you can see uint32Value also works correctly. However, none of the 64 bit variants work.

只要您确定结果可以放入Int32中,您就可以将其用作变通方法,直到他们修复它为止,考虑到该错误已经存在了一段时间,这可能永远不会解决.

Provided you are sure that your result will fit into an Int32 you can use that as a work around until they fix it, which is probably never, given that the bug has been outstanding for a while.

这篇关于NSDecimalNumber(x).intValue返回-2、0、15和199,具体取决于x中的小数位数(x = 199.999 ... 5)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆