这个样本家庭作业问题的答案是“1,000,000”,但我不明白为什么:
以下代码的输出是什么?
int main(void) {
float k = 1;
while (k != k + 1) {
k = k + 1;
}
printf(“%g”, k); // %g means output a floating point variable in decimal
}
如果程序无限期运行但没有输出,请写INFINITE LOOP作为问题的答案。所有程序都编译运行。但是,它们可能包含或可能不包含严重错误。您应该假设int是四个字节。您应该假设float具有相当于六位小数的精度。你可以将你的答案四舍五入到最接近的10的幂(例如,你可以说1000而不是2 10 (即1024))。
我不明白为什么循环会终止。
答案 0 :(得分:15)
由于浮点数不完美的简单原因,它不会永远运行。
在某些时候,k
会变得足够大,因此向其添加1将不起作用。
此时,k
将等于k+1
,您的循环将退出。
只有当浮点数在某个范围内时,它们才能由一个单位区分。
例如,假设您有一个整数类型,其中包含3个十进制数字的精度,用于正整数和单个十进制数字的指数。
有了这个,你可以完美地将数字0到999表示为000x10 0 到999x10 0 (因为10 0 是1):
当你想代表1000时会发生什么?您需要使用100x10 1 。这仍然很完美。
但是,没有使用此方案表示1001的准确方法,您可以表示的下一个数字是101x10 1 ,即1010。
因此,当您添加1到1000时,您将获得最接近的匹配,即1000。
答案 1 :(得分:6)
代码使用float
变量。
如问题中所述,float
具有6位精度,这意味着第六位之后的任何数字都将是不准确的。因此,一旦你通过一百万,最后的数字将是不准确的,所以增加它可能没有效果。
答案 2 :(得分:4)
由于未指定float
类型的语义,因此C标准的此程序的输出未指定。一个可能的结果(您将在IEEE {754单精度中评估float
算术的平台上得到的结果)是2^24
。
小于2^24
的所有整数都可以在单精度中精确表示,因此计算不会在该点之前停止。然而,2^24
之后的下一个可表示的单精度数字是2^24 + 2
。由于2^24 + 1
正好位于该数字和2^24
之间,因此在默认的IEEE-754舍入模式中,它会舍入到尾随位为零的那个,即2^24
。
其他可能的答案包括2^53
和2^64
。还有其他答案是可能的。例如,Infinity
(浮点值)可能导致默认舍入模式向上舍入的平台。正如其他人所指出的那样,在更广泛的类型中评估浮点表达式的平台上也可能存在无限循环(这是各种程序员混淆的根源,但C标准允许)。
答案 3 :(得分:3)
实际上,在大多数C编译器中,这将永远运行(无限循环),但精确的行为是实现定义的。
大多数编译器会给出一个无限循环的原因是它们以 double 精度计算所有浮点表达式,并且只将值返回到 float (单个)精度时存储到变量中。因此,当k的值达到大约2 ^ 24时,k == k + 1
仍将评估为false(因为double可以保持值k + 1而不进行舍入),但k = k + 1
赋值将是noop ,因为k + 1需要四舍五入以适合浮动
修改强>
x86上的gcc获得了这种无限循环行为。有趣的是在x64上没有,因为它使用了以浮点精度进行比较的sse指令。