【问题标题】:float variables in C [duplicate]C中的浮点变量[重复]
【发布时间】:2012-10-25 09:58:49
【问题描述】:

这可能是一个简单的问题,但我不确定浮点变量是如何存储在内存中的,以及为什么它会以这种方式表现,有人可以解释一下以下行为吗?

#include<stdio.h>

int main ()
{
    int a = 9/5;
    printf("%f\n", a);
    return 0;
}

输出:

0.000000

我查看了一些关于浮点变量如何存储在内存中的信息,它包含关于尾数、指数和符号的内容。但我不知道如何在这里联系。

【问题讨论】:

  • 整数除法...不匹配printf格式说明符...
  • 你也应该在这里查看:stackoverflow.com/questions/11673503/…
  • 我不想在这里修复,我知道这一点,只想知道为什么以及在这种情况下发生了什么!

标签: c format-specifiers


【解决方案1】:
int a = 9/5;

执行整数除法并忽略余数,因此 a 设置为 1。尝试使用 %f 打印会产生未定义的行为,但碰巧你得到了 0.000000

double a = 9./5.;

相反,如果整数除法是所需的行为,则使用%d 打印。 (float 也可以,但a 在传递给printf 时会提升为double,因此没有理由不使用double。)

【讨论】:

  • 商会变成a,而不是余数。
  • 这样a应该设置为1是nt吗?
  • @ManikSidana:是的,所以它忽略其余部分
  • @Aniket:我的想法,已修复。但除法的结果是什么并不重要;将 int 传递给 printfdouble 预期为 UB。
  • @codewarrior:在可变参数的情况下。
【解决方案2】:

这是一种未定义的行为。

您正在使用浮点格式说明符 (%f) 来打印 int (a)。您应该使用%d 来查看正确的输出。

【讨论】:

    【解决方案3】:

    这是 C 中未定义的行为。使用 %d 格式说明符而不是 %f

    Does printf() depend on order of format specifiers?给你详细解答。

    【讨论】:

      【解决方案4】:

      以下是对您的代码的简要分析:

      int a = 9/5; // 9/5 = 1.8, but since you are doing integer division and storing the value in an integer it will store 1.
      printf("%f\n", a);//Using incorrect format specifiers with respect to datatypes, will cause undefined behavior
      
      printf("%d\n",a);//This should print 1. And correct.
      

      或者如果你想要浮动:

      而不是int 使用float

         float a=9.0f/5;//This will store 1.800000f
         //float a=9/5 will store 1.000000 not, 1.8 because of integer divison 
         printf("%f\n",a); //This will print 1.800000
      

      另请阅读:http://en.wikipedia.org/wiki/IEEE_754-2008 了解浮点的工作原理。

      关于整数除法的说明:

      C99: 6.5.5 乘法运算符

      6 整数相除时,/ 运算符的结果是去掉任何小数部分的代数商。88) 如果商a/b 是可表示的,则表达式@ 987654329@ 应等于 a

      88) 这通常被称为“向零截断”。

      【讨论】:

      • 9/5 进行整数除法。你的意思可能是 9.0/5.0f
      • 9/5 不是 1.8,而是 1,因为 9 是 int 而 5 是 int。无论您尝试将 1 存储到 int 还是 float 中,都不会影响计算。
      • P.S: 关于乘法运算符 6 整数除法时,the result of the / operator is the algebraic quotient with any fractional part discarded.88) 如果商 a/b 是可表示的,则表达式 (a/b)*b + a%b 应等于 a .我必须说,整数是结果,由于截断为零。
      【解决方案5】:

      仅仅假设你的除法应该在正常数学中产生一个分数并不会神奇地使它成为一个浮点数。

      int a = 9/5;
      

      你需要使用

      float a = 9.0/5;
      

      首先,您需要正确的数据类型,即浮点数(或更好的双精度以获得更高的精度)来存储浮点数。

      其次,如果您要对两个整数(即 9 和 5)进行除法,它将简单地遵循整数除法,即仅存储除法的整数部分并丢弃其余部分。为了避免我在 9 之后添加了 .0。这将强制编译器隐式转换为浮点数并进行除法。

      关于您提到它为什么打印 0,已经提到在整数上尝试 %f 是未定义的行为。从技术上讲,浮点数是 4 个字节,包含 3 个字节数和 1 个字节指数,它们结合起来生成结果值。

      【讨论】:

      • 9/5 实际上是 1。所以这不是他想要的。为什么浮点到整数的转换对于这个特定问题的值为 0.00
      • 9/5 实际上是 1 很明显。我从问题中粘贴了它并在其下添加了正确的版本以澄清差异。我说他在哪里找 1??
      • 严格来说你应该写float a = 9.0f / 5.0fdouble a = 9.0 / 5.0。在您编写此示例时,您强制对双精度数进行计算,然后将其截断为浮点数。你使代码更加无效,没有任何收获。如果幸运的话,编译器可能足够聪明,可以优化,但不要指望它。
      • 没错,但非常“严格来说”。考虑到提出问题的人。对 double 或 float 的偏好应该不碍事。作为一名老师,我总是学会说明而不是使话题复杂化。即使降级为浮点数,也能达到生成浮点值的目的,尽管精度较低。我当然不认为这是投反对票的理由或考虑以上更好的解释。但是每个人都有自己的看法:)
      猜你喜欢
      • 2020-04-18
      • 2012-10-26
      • 1970-01-01
      • 1970-01-01
      • 2015-02-17
      • 1970-01-01
      • 1970-01-01
      • 2015-09-06
      • 1970-01-01
      相关资源
      最近更新 更多