Sim*_*mon 4 int decimal rounding nsdecimalnumber swift
我们在业务逻辑中发现了一个有趣的案例,它完全打破了我们的逻辑,我们不明白为什么NSDecimalNumber
,也不Decimal
知道它的行为方式。
我的案例游乐场如下:
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
Run Code Online (Sandbox Code Playgroud)
在上面的游乐场代码中,如果您不想自己运行它,则如果向右滚动,您可以看到返回值。
在计算将这些数量平均分配多少以产生美观的价格时,我们需要将原始小数值、数量和价格暂时转换为整数。然而,在这种情况下,由于某种原因,我们不能,因为转换的初始步骤失败,产生一个0
而不是200
(是的,当前的代码会产生199
一个错误)。
为什么 NSDecimalNumber 根据小数位数(范围从-2
到 )返回这些奇怪的值199
?
我们的解决方案是在将内部计算放入 之前对其进行四舍五入NSDecimalNumber
,但我们首先想知道其原因。这是一个错误还是预期的结果并且人们应该意识到它可能会发生?
这显然是一个基础错误,可能是 Martin R在评论中提到的。
我在 Playground (Swift 5) 中进行了实验,发现有关该错误int32Value
正常工作的评论是正确的。
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
Run Code Online (Sandbox Code Playgroud)
另外,正如您所看到的,uint32Value
也可以正常工作。但是,64 位变体都不起作用。
如果您确定您的结果适合Int32
您可以使用它作为解决方法,直到他们修复它,考虑到该错误已经存在了一段时间,这可能永远不会。
归档时间: |
|
查看次数: |
725 次 |
最近记录: |