为什么NSString类在格式化数字时不一致?

下面两行的输出似乎表明,NSString的stringWithFormat语句不会一致地舍入数字。 似乎从0.75到0.8正确地凑齐了。 但是它下降了0.25到0.2。 这是代码。

NSString *sRoundedScore = [NSString stringWithFormat:@"%.1f", fScore]; NSLog(@"\r\n score before rounding: %f, rounded score: %@", fScore, sRoundedScore); 

当fScore分配为0.25时,输出为:

 score before rounding: 0.250000, rounded score: 0.2 

当fScore分配为0.75时,输出为:

 score before rounding: 0.750000, rounded score: 0.8 

我不得不开始使用NSNumberFormatter来使这个循环一直向上。 为什么stringWithFormat会在结果中产生这种变化?

这个答案可以追溯到“printf”function

银行家四舍五入:

重要的是要知道这是更多的说明,你要在浮点整数显示一个小数位。

既然你说的是一个小数点,它正在检查第二个小数来决定在哪里舍入。 %.f格式的舍入逻辑是这样工作的:如果你的号码直接前进在4以下,那么如果你的号码直接前进到4以上5以上,则舍去5。

原因是这样的: http : //linuxgazette.net/144/misc/lg/a_question_of_rounding_in_issue_143.html :“对于GNU C库,printf()使用的舍入规则是”银行家舍入“或”舍入到均匀“。比其他一些C库更正确,因为C99规范认为转换为十进制应该使用当前select的IEEE舍入模式(默认银行家四舍五入)。

从这个答案中find: printf四舍五入行为的双打

如果你想在上面的内联中做一个普通的四舍五入 ,可以使用函数round()和一些小math来实现,或者你可以简单地使用NSNumberFormatter

在Objective-C中舍入数字

根本问题是,当你看到0.25时,这个数字实际上更像是0.2499999999999。 有一些标准的技术来获得你想要的舍入。 在这个特殊情况下,你可以乘以100.0f的浮点数,然后使用lroundf,并打印长:

 float foo = 0.25f; NSLog(@"First %f", foo); NSLog(@"Round %.1f", foo); foo += 0.0000001; NSLog(@"Second %f", foo); NSLog(@"Round %.1f", foo); //2013-07-18 15:36:09.021 EmailAddressFinder[12618:303] First 0.250000 //2013-07-18 15:36:09.022 EmailAddressFinder[12618:303] First 0.2 //2013-07-18 15:36:09.022 EmailAddressFinder[12618:303] Second 0.250000 //2013-07-18 15:36:09.022 EmailAddressFinder[12618:303] Second 0.3 foo = 0.25f; foo *=100; long l = lroundf(foo); NSLog(@"l=%ld", l); NSLog(@"0.%0.2ld", l); // .2=="print two places", 0=="add a leading 0 if needed" //2013-07-18 15:37:24.424 EmailAddressFinder[13474:303] 0.25 

你将需要调整范围等。每当我使用美元货币时,我总是这样用整数美分,并使用一种小的方法给我一个美元。

编辑:我看到你给了一个答案 – 任何人使用printf的行为,以确定他们的用户将看到什么将有问题的某些时候。 把这些数字合并成你知道的东西,你将拥有健壮和可移植的代码。

Interesting Posts