繁体   English   中英

如何从字符串解析十进制而不损失精度?

[英]How to parse Decimal from String without losing precision?

我正在处理我的应用程序中的金额,因此精度显然非常重要,并且Decimal / NSDecimal数字应该是迅速处理金钱的方式。 我想在保持精度的同时在Decimal和String之间转换。 (解析API响应,存储到数据库...)

这是我目前的解决方案:

private let dotLocaleDictionary = [NSLocale.Key.decimalSeparator: "."]

func apiStringToDecimal(_ string: String) -> Decimal? {
    let number = NSDecimalNumber(string: string, locale: dotLocaleDictionary) as Decimal
    return number.isNaN ? nil : number
}

func decimalToApiString(_ decimal: Decimal) -> String {
    return (decimal as NSDecimalNumber).description(withLocale: dotLocaleDictionary)
}

语言环境字典负责小数点分隔符,我希望字符串初始化程序是精确的。 但是在操场上玩耍时,我注意到在输入字符串一定长度后,所得的数字被截断了。

我也尝试使用数字格式化程序解析字符串,但结果甚至更糟。

我的游乐场代码:

let small = "1.135160000500009000100020003000400050061111"
let big = "1234567890123456789000100020003000400061111"
let medium = "123456789123456789.0001000200030004000511111"
let negative = "-123456789123456789.0001000200030004000511111"
let numericStrings = [small, big, medium, negative]

numericStrings.forEach {
    print($0)
    guard let decimal = apiStringToDecimal($0) else {
        print("Failed to parse decimal from: \($0)")
        print("--------------------")
        return
    }

    print(decimal)
    let string = decimalToApiString(decimal)
    print($0 == string ? "match" : "mismatch")

    print("--------------------")
}

let max = Decimal.greatestFiniteMagnitude
print("MAX decimal: \(max)")
print((max as NSDecimalNumber).description(withLocale: dotLocaleDictionary))
print(decimalToApiString(max))

并产生输出:

1.135160000500009000100020003000400050061111
1.13516000050000900010002000300040005006
mismatch
--------------------
1234567890123456789000100020003000400061111
1234567890123456789000100020003000400060000
mismatch
--------------------
123456789123456789.0001000200030004000511111
123456789123456789.000100020003000400051
mismatch
--------------------
-123456789123456789.0001000200030004000511111
-123456789123456789.000100020003000400051
mismatch
--------------------
MAX decimal: 3402823669209384634633746074317682114550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
3402823669209384634633746074317682114550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
3402823669209384634633746074317682114550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

从十进制转换为字符串似乎可以正常工作,从字符串转换为十进制似乎是问题所在。 由于我的数字小于最大十进制数,因此我认为我的测试数字不会太大。 我敢肯定,我已经排除了打印问题,并且已经在实际设备上运行了代码,所以这不是操场问题。

难道我做错了什么? 有没有更好的方法来快速在小数和字符串之间转换?

还是字符串太长? (我没有找到任何文档/讨论为什么不起作用)

NSDecimalNumber

NSDecimalNumber是NSNumber的不可变子类,它提供了一个面向对象的包装器,用于进行10进制算法。 一个实例可以表示任何可以表示为尾数x 10 ^指数的数字 ,其中尾数是不超过38位长的十进制整数,指数是从–128到127的整数。

(强调我的)

虽然NSDecimalNumber提供高精度的十进制算术,但精度有极限。

您可能需要一个自定义库,例如BigNum

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM