【问题标题】:Why is x and y always 0 with a float?为什么 x 和 y 总是 0 并带有浮点数?
【发布时间】:2009-10-01 16:50:45
【问题描述】:
int main(void){
    float x =1;
    float y =2;
    while (x<y){
        x = x +1 ;
        y = y +1;
}
    printf("x is %d\n", x);
    printf("y is %d\n", y);
}

我希望 x 和 y 增加到我们用完比特的程度,但在这种情况下 x 和 y 似乎总是 0...

【问题讨论】:

  • 这个错误很容易犯,但犯错的人却很难。问别人,你会在一分钟内得到答案:)
  • 事实上,浮点数没有 printf 转换说明符。转换说明符%f 需要一个双精度参数:幸运的是,当调用 printf() 时,浮点参数被转换为双精度参数。我的建议:永远不要使用花车;总是使用双打。

标签: c floating-point


【解决方案1】:

正如其他人所说,您应该使用%f 格式来打印浮点数,而不是用于整数的%d。还有%e,它以科学计数法而不是固定计数法打印浮点数,还有%g,它以科学计数法或固定计数法打印,以较短者为准。

它打印为 0 的原因是因为浮点参数在作为参数传递给可变参数函数(即采用未指定数量参数的函数)时会自动转换为双精度数,例如 printf()。数字 2 和 3(xy 的值)作为双精度数的表示分别为 0x4000000000000000 和 0x4008000000000000,由 IEEE-754 Floating-Point Conversion calculator 计算得出。

在 little-endian 机器上(例如任何基于 x86 的机器),%d 修饰符从堆栈中抓取接下来的 4 个字节并将它们解释为整数。因此,当您传递浮点数 2 时,它会转换为 0x4000000000000000 的双精度数,在 little-endian 中是 00 00 00 00 00 00 00 40。前四个字节使整数 0,这就是打印出来的内容。

请注意,如果您在一个语句而不是两个语句中打印两个数字,您会得到更令人惊讶的结果:

printf("x=%d y=%d\n", x, y);
// Output: x=0 y=1073741824

如果您将警告级别设置得足够高,大多数编译器都会警告您这些类型的错误。使用 GCC,您应该使用 -Wformat 选项(或 -Wall,其中包括 -Wformat)进行编译,当您尝试使用 %d 打印浮点数时,它会警告您。

【讨论】:

  • 完全正确,除了在达到 printf 语句时 x 和 y 都应该是 2^24(单精度 2^24 + 1 舍入到 2^24)。作为双精度数,2^24 是 0x4170000000000000,因此您的其余分析可以正常进行。
  • (而且,和往常一样,如果您使用的编译器选择在 80 位扩展中进行部分或全部浮点计算,那么所有的赌注都会被取消。)
【解决方案2】:

%d 是一个整数。

http://www.cplusplus.com/reference/clibrary/cstdio/printf/

使用 %f 表示浮点数:

printf("x is %f\n", x);
printf("y is %f\n", y);

【讨论】:

    【解决方案3】:

    有一件事:你不应该在 printf 中使用 %d 来表示浮点数,而是使用 %f、%e 或 %g

    【讨论】:

      【解决方案4】:

      我希望 x 和 y 增加到我们用完比特的程度

      不,当您用完精度时,循环将停止。我相信在某个时候这个数字会足够大,以至于 1.0f 的增量太小而无法表示,并且 x 将等于 y。

      当你修复你的输出格式时,我猜你会看到这种情况。

      【讨论】:

      • 特别是:2^24,如果您的编译器实际上以单精度执行所有浮点计算。
      【解决方案5】:

      %d 代表整数,使用 %f。

      你会用完位但不完全像一个整数,你最终会溢出指数,这应该会导致异常,尽管你可能不知道。我忘记了这是否会导致 nan 或 infinity。这使得不太有趣。我想知道为什么 while 循环不会永远运行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-08-22
        • 1970-01-01
        • 2019-07-18
        • 2014-11-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-01
        相关资源
        最近更新 更多