我发现了
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
即使我尝试将其四舍五入到小数点后两位
avg = roundf(avg * 100); // here 105
avg = avg / 100; // and here is 1.0499999523162842 again
但是,如果我测试代码并手动将 1.05 放入
NSDictionary
中,一切都会按预期工作。
如果有人可以解释这是为什么?以及如何保存每次正确的显示?
问题是1.05的值无法用浮点数精确表示。这仅适用于 2 的(正或负)幂之和的值。因此,可以精确地表示 1 (=2^0) 或 1.03125 (= 2^0 + 2^-5) 等值,但是1.5 的最佳近似值是您的情况 1.0499999523162842。
现在,当您初始化
NSNumberFormatter
并且不设置其 roundingMode
属性时,其默认值为 kCFNumberFormatterRoundHalfEven
,这意味着数字将“向最接近的整数舍入,如果等距则向偶数舍入。”