Swift中NSDecimalNumber处理货币精度问题求助
解决Core Data中NSDecimalNumber的浮点精度问题,精准得到0.07
嘿,太懂你这种不想来回转类型的麻烦了——用Core Data绑定NSDecimalNumber本来就是为了规避浮点精度坑,但有时候还是会踩雷对吧?别担心,只要调整几个使用细节,就能精准得到你要的0.07,完全不用大量转换类型。
核心问题:别用浮点数初始化NSDecimalNumber
很多时候精度问题的根源不是NSDecimalNumber本身,而是你用了double类型的字面量来初始化它。比如[NSDecimalNumber decimalNumberWithDouble:0.01],因为0.01在二进制浮点数里是无法精确表示的,转成NSDecimalNumber的时候就带了隐形误差,后续运算自然会出问题。
正确的打开方式:用字符串初始化
改用字符串来创建NSDecimalNumber,就能直接基于精确的十进制值初始化,从根源避免误差:
// 用字符串初始化,确保值完全精确 NSDecimalNumber *num1 = [NSDecimalNumber decimalNumberWithString:@"0.01"]; NSDecimalNumber *num2 = [NSDecimalNumber decimalNumberWithString:@"0.06"]; // 使用NSDecimalNumber的专属运算方法 NSDecimalNumber *result = [num1 decimalNumberByAdding:num2]; // 这里result就是精确的0.07
Core Data层面的保障
确保你的Core Data实体属性类型是Decimal(不要选Float或Double),这样数据存入和取出时都是以十进制精确存储的,不会在持久化环节引入误差。
处理舍入需求(比如货币保留两位小数)
如果需要对结果做舍入处理(比如货币场景固定两位小数),可以用NSDecimalNumberHandler指定舍入规则,避免手动转换带来的问题:
// 创建舍入规则:四舍五入,保留两位小数 NSDecimalNumberHandler *roundingHandler = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:2 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:YES]; NSDecimalNumber *rawResult = [num1 decimalNumberByAdding:num2]; NSDecimalNumber *finalResult = [rawResult decimalNumberByRoundingAccordingToBehavior:roundingHandler];
关键提醒
永远用NSDecimalNumber自带的运算方法(decimalNumberByAdding:、decimalNumberByMultiplyingBy:等)做计算,不要把它转成double再运算——一旦转成double,之前的精确性就全白费了。
内容的提问来源于stack exchange,提问作者LateNate
相关产品推荐
相关产品推荐

