【问题标题】:NSNumber is not the same as its floatValueNSNumber 与其 floatValue 不同
【发布时间】:2016-01-25 14:48:21
【问题描述】:

我遇到了NSNumber 的奇怪行为。

基本上我的代码从 API 调用中获取 json:

id json_response = [NSJSONSerialization
                             JSONObjectWithData:data
                             options:NSJSONReadingMutableLeaves
                             error:&error];

并存储为NSDictionary

然后我从中得到NSNumber 并使用NSNumberFormatter 将其转换为字符串,但是...

NSNumber * avgNumber = [[_tableDataArray objectAtIndex:index ]
                            objectForKey:kTrendsKeyAvgScoreFloat];

这是格式化输出:

 NSNumberFormatter * formatter = [[NSNumberFormatter alloc]init];
[formatter setDecimalSeparator:@","];
[formatter setMaximumFractionDigits:1];
[formatter setMinimumFractionDigits:0];
[formatter setGroupingSeparator:@"."];
[formatter setGroupingSize:3];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSString * retString = [formatter stringFromNumber:number];

当NSNumber 的值为 1.05 时,我的行为很奇怪

(__NSCFNumber *) avgNumber = 0x0000000155923800 (float)1.050000

但上面的代码正在打印(而不是预期的 1.1):

1

但是当我检查浮点值时

float avg = [avgNumber floatValue];

原来是这样的

    Printing description of avg:
(double) avg = 1.0499999523162842

即使我尝试将其四舍五入到小数点后 2 位

    avg = roundf(avg * 100); // here 105
    avg = avg / 100; // and here is  1.0499999523162842 again

但是,如果我测试代码并将 1.05 手动放入 NSDictionary 中,一切都会按预期工作。

如果有人能解释为什么会这样?以及如何保存每次正确显示?

【问题讨论】:

  • 不清楚您的问题是什么。是NSNumberFormatter 产生1 而不是1.1?在这种情况下,这是因为它向下舍入。或者您是否对1.04999 而不是1.05 感到困惑?在这种情况下,这只是一个浮点舍入错误。
  • 是的,我很困惑,因为我有 1.05,它应该四舍五入到 1.1 而不是 1。

标签: ios objective-c nsdictionary nsnumber


【解决方案1】:

问题是 1.05 的值不能用浮点数精确表示。这仅适用于 2 的(正或负)幂的总和。因此,可以精确表示像 1 (=2^0) 或 1.03125 (= 2^0 + 2^-5) 这样的值,但是在您的情况下,1.5 的最佳近似值是 1.0499999523162842。
现在当你初始化一个NSNumberFormatter,并且不设置它的roundingMode属性时,它的默认值是kCFNumberFormatterRoundHalfEven,这意味着这个数字将被四舍五入“向最接近的整数,或者如果等距则向偶数。” 所以如果你的数字是1.0499999523162842,它会四舍五入到1.0,输出为1。

【讨论】:

  • 这对我来说非常清楚,谢谢。那么如何向最终用户显示正确的数字呢?因为即使使用正确的舍入模式也无济于事,因为它会舍入 1.0499999523162842 而不是 1.05
  • 如果您不想向整数舍入,而是向整数的一半舍入(在您的情况下向 1,05),您可以这样做:如果 x 是要舍入的值,则舍入 2x一个整数,然后将结果除以 2。例如1,0499 * 2 = 2,0998,四舍五入 = 2,1 / 2 = 1,05。但是,如上所述,1,05 不能用浮点数精确表示。
猜你喜欢
  • 2011-02-18
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
  • 2010-11-16
  • 1970-01-01
  • 2016-07-26
  • 2011-02-01
相关资源
最近更新 更多