将 NSString 转换为 NSNumber 会导致数字过多和奇怪的舍入

Posted

技术标签:

【中文标题】将 NSString 转换为 NSNumber 会导致数字过多和奇怪的舍入【英文标题】:Converting NSString to NSNumber results in too many digits and strange rounding 【发布时间】:2012-07-03 17:44:17 【问题描述】:

在将包含两位标准十进制数字(例如 8.20)的 NSString 转换为 NSNumber 时,当通过 @987654323 记录结果时,我(不时)得到额外的数字和奇怪的舍入行为@ 或将其保存在 Core Data 中(作为浮点数或双精度数),例如8.20 -> 8.199999999999999。

这是我用来转换数字的代码:

 NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
 [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
 [numberFormatter setMaximumFractionDigits:5];
 NSNumber *num = [numberFormatter numberFromString:str];

我不明白为什么转换为 NSNumber 会弄乱数字。我的代码有什么问题?

【问题讨论】:

请教授解释“浮点数”。 【参考方案1】:

这就是 float 和 double 在 C/Objective-C(以及许多其他语言)中的行为方式。例如,当您输入 python 8.0 时,结果将是 8.000000000001。我建议使用NSScanner 将它们转换为原始数字类型(double、float)。

【讨论】:

但是如果Core Data存储的是8.00000001而不是8.0会正确吗? 换一种说法 - 双精度浮点数无法准确表示最常见的分数。您只知道输入的数字 - 您输出的数字应该精确到大约 10^15 的一部分。 正确。这就是为什么不建议使用 == 比较两个浮点数/双精度数的原因。 (float1 == float2 不好。Abs(float1 - float2) <= epsilon 好。) @AlexR:如果您想了解为什么这是正确的行为,请参阅docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html。如果你不想读那句话,那就接受它是真的。 感谢大家澄清这一点。你很有帮助。由于我处理的数据主要是货币数据,所以我现在使用 NSDecimalNumber 而不是 float 和 double。你对 NSDecimalNumber 有什么看法?【参考方案2】:

为什么要使用 NSNumberFormatter 将字符串转换为浮点数,这将是一个矫枉过正, 要转换它,只需使用

NSNumber *num = [NSNumber numberWithFloat:[str floatValue]];

【讨论】:

【参考方案3】:

我在使用 NSNumber 保存双值时遇到了问题 8.28 总是显示 8.2799999999 ......,我猜它是由计算机数值精度引起的 试试这个代码。

 + (NSString *)dealWithDouble:(double)doubleValue 
        double d2 = doubleValue;
        NSString *d2Str = [NSString stringWithFormat:@"%lf", d2];
        NSDecimalNumber *num = [NSDecimalNumber decimalNumberWithString:d2Str];
        NSString *str2D = [num stringValue];
        return str2D;
    

【讨论】:

【参考方案4】:

不要使用浮点值。 floatValue 仅提供 24 位精度。 doubleValue 给出 53 位精度。例如,如果您使用超过一百万美元的数字,floatValue 无法为您提供任何相差小于 6 美分的值。 (1,000,000 美元,然后是 1,000,000.06 美元等)

规则是:除非你知道你应该使用float而不是double的原因,否则不要使用float。

【讨论】:

使用双精度计算货币也是非常错误和愚蠢的。 fixed 精度必须用于货币。 如果您知道自己在做什么并避免迷信,使用 double 进行货币计算绝对没问题。

以上是关于将 NSString 转换为 NSNumber 会导致数字过多和奇怪的舍入的主要内容,如果未能解决你的问题,请参考以下文章

将核心数据中的 NSNumber 转换为 NSString

将 NSString 转换为 NSNumber 精度问题

如何将 NSNumber 转换为 NSString

将 NSString 转换为特定于语言环境的 NSNumber

在 CoreData 实体中将属性从 NSNumber 转换为 NSString - LightWeightMigration

React Native - nsnumber类型的json值'0'无法转换为nsstring