2013-04-05 35 views
2

在这种情况下(对象 - ,的iOS):舍入当[INT] = [浮子] + [INT]

float a = 0.99999f; 
int b = 1000; 
int c = a + b; 

在结果c = 1001。我发现它发生是因为b转换为float(特定于iOS),因此a + b没有足够的精度来处理1000.9999和(为什么?)被四舍五入为较高值。如果a0.999f,我们得到c = 1000 - 理论上正确的行为。

所以我的问题是为什么浮点数四舍五入到更高的价值?描述这种行为(或惯例)的地方?

我在iPhone Simulator,Apple LLVM 4.2编译器上测试了这个。

+0

这里我越来越1000. – Balu 2013-04-05 11:38:26

+0

也刚刚开始1000 – 2013-04-05 11:38:45

+0

我的错误,人。 'a = 0.99999f' – brigadir 2013-04-05 11:46:40

回答

4

int c = a + b中,首先将整数b转换为浮点数,然后再添加2个浮点数 ,并将结果截断为整数。

默认浮点舍入模式是FE_TONEAREST,这意味着结果添加

0.99999f + 1000f 

的 是可以被表示为浮点数的最接近数目,这是数1001f。这个浮点数然后被截断为整数c = 1001

如果更改舍入模式

#include <fenv.h> 
fesetround(FE_DOWNWARD); 

然后相加的结果向下取整(约1000.99993f),你会得到c = 1000

+0

关闭,但不完全正确。用于表示浮点数加法结果的*最接近的*值类似于1001.000032(从空中拉出一个数字),所以结果四舍五入至此。然后,根据标准C规则,该数字在float-> int转换中被截断*为1001。 – 2013-04-05 14:35:48

+0

@HotLicks:我不太明白。为什么最近的浮动点到0.99999 + 1000为1001.000032而不是1001? 1001 *是*可表示为浮点数,并且比1001.000032更接近1000.99999。 (在给出答案之前,我也在调试器中验证了这一点)。 - 也许我完全错过了某些东西? – 2013-04-05 14:48:38

+0

是的,我想你是对的 - 小整数在IEEE浮点数中完全可以表示。但需要强调的是,发生的舍入是将float值转换为最接近的IEEE表示,而不是舍入到整数。本质上舍入为1001.00000,而不是1001. – 2013-04-05 16:01:40

1

原因是,当你加1000时,你会得到8位总精度的十进制数,但IEEE浮点数只支持7位数。

+0

但为什么这个数字是四舍五入的?外围数字应该被切断(就像'float' - >'int'转换一样)。 – brigadir 2013-04-05 12:01:43

+0

@brigadir - 实质上,总和的计算使用更高的精度,并且可以产生1000.9999932的结果。但是这不能表示为32位浮点数。所以最接近的两个“合法”值可能是1000.9999843和1001.0000017。在默认舍入模式下,FP单元选择后者,因为它更接近“真实”答案。 – 2013-04-05 14:33:11