1

以下两行的输出似乎表明 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 会在结果中产生这种变化?

4

2 回答 2

3

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

银行家四舍五入:

重要的是要知道这更说明您希望在浮点整数上显示一位小数。

由于您说的是小数点后一位,因此它正在检查第二个小数点以决定在哪里四舍五入。%.f format'er 的舍入逻辑是这样工作的:如果你前面的数字小于 4,那么如果你前面的数字是 4 并且大于 5,则向下取整 5。

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

从这个答案中找到: printf rounding behavior for doubles

如果你想在上面做一个常见的四舍五入,请使用 c 函数round()和一些数学来完成这个技巧,或者你可以简单地使用NSNumberFormatter,如你所说。

Objective-C 中的舍入数字

于 2013-07-18T14:42:59.083 回答
1

根本问题是当你看到 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

您将需要调整范围等。每当我使用美元时,我总是以这种方式四舍五入到整数美分,并使用一种小方法通过使用相同的技术从仅美分给我一个 Dollar.cents 字符串。

编辑:我看到你得到了一个答案——任何使用 printf 的行为来确定他们的用户将看到什么的人都会在某个时候遇到问题。将数字强制转换为您确定的数字,您将拥有健壮且可移植的代码。

于 2013-07-18T14:51:23.830 回答