将字符串转换为NSDecimalNumber

13

我尝试将一个字符串转换为NSDecimalNumber,这是我的代码:

class func stringToDecimal (dataToDecimal: String) -> NSDecimalNumber {

    let dataToDecimal = dataToDecimal.stringByReplacingOccurrencesOfString(",", withString: ".")
    print(dataToDecimal)
    let  decimalReturn = NSDecimalNumber(string: dataToDecimal)
    print(decimalReturn)

    if decimalReturn == NSDecimalNumber.notANumber(){
        return 0.00
    }
    return decimalReturn
}

起初我认为可能是逗号的问题,但即使用句点也不行。第一个打印(在转换之前)显示例如80,00,但打印decimalReturn只显示80。

if语句仅用于检查结果是否为数字。

3个回答

23

使用NSNumberFormatter解析您的输入。将其generatesDecimalNumbers属性设置为true:

let formatter = NumberFormatter()
formatter.generatesDecimalNumbers = true

如果想在字符串无法解析时返回0,以下是使用方法:

func decimal(with string: String) -> NSDecimalNumber {
    return formatter.number(from: string) as? NSDecimalNumber ?? 0
}

decimal(with: "80.00")

// Result: 80 as an NSDecimalNumber

默认情况下,格式化程序将查看设备的区域设置以确定小数点标记。您应该保持这种方式。为了举例,我将强制使用法语区域设置:

// DON'T DO THIS. Just an example of behavior in a French locale.
formatter.locale = Locale(identifier: "fr-FR")

decimal(with: "80,00")
// Result: 80

decimal(with: "80.00")
// Result: 0

如果你想始终使用逗号作为小数点符号,可以设置decimalSeparator属性:
formatter.decimalSeparator = ","

它起作用了,但我必须先执行 let dataToDecimal = dataToDecimal.stringByReplacingOccurrencesOfString(",", withString: "."),将我的字符串转换为非空值。如果我只尝试一个带有“,”的字符串,它将返回nil。 - HongKongTom
2
我读过NSDecimal在计算方面是精确的,但如果我输入80.01,结果会变成80.01000002,如果我输入80.10,结果会变成80.09999999。你怎么把数字减少到2位? - HongKongTom
我想知道,这与“Decimal(string:“80,00”,locale:Locale.current)”有什么不同? - Sulthan
@robmayoff 我不相信那是真的。NSDecimalNumber 一直有那个初始化方法。如果你注意到了,所有 Decimal 的方法都标记为 iOS 10+ - Sulthan
你说得对。我正在查看Swift文档,Decimal类中的所有内容都可以在2016年的操作系统版本中使用。 - rob mayoff
显示剩余2条评论

4
你从字符串中创建 NSDecimalNumber 的方式没有问题。但是,如果你的本地格式是用逗号分隔数字,就不需要担心将逗号替换为句点。
它打印 80 而不是 80.00 或 80,00 的原因是 print 只使用数字的 description 属性。如果你想自定义格式,请设置自己的 NSNumberFormatter
let number = NSDecimalNumber(string: "80.00")
print(number) // 80
let formatter = NSNumberFormatter()
formatter.minimumFractionDigits = 2
let string = formatter.stringFromNumber(number)
print(string) // 80.0

我尝试了一下,但在实际项目和游乐场中,它会出现错误消息“无法将类型为“String”的值转换为预期的参数类型“NSNumber”,但是...minimumFractions我喜欢并且会使用它。 - HongKongTom
你的代码可能存在另外一个问题。我在 Playground 中发布的代码表现良好。 - Craig Siemens

0

当服务器强制使用某些特定的语言环境时,应该使用它来代替Locale.current,否则可能会因用户设置而导致故障。

extension String {
    var decimalFromServerString: NSDecimalNumber? {
        let parsed = NSDecimalNumber(string: self, locale: ru_ru_posix)
        if parsed == .notANumber {
            return nil
        }
        return parsed
    }
}

顺便说一句,如果你因为某种原因将本地设置为en_US POSIX,那么字符串“...”会变成0。想象一下吧 :-[


如果数字中有千位分隔符,这似乎无法正常工作。 - mliu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接