C语言中的浮点数很奇怪

Floating point is very weird in C language

C 语言中的浮点数很奇怪。我知道它通常用作 (float)a/b。不过我很好奇下面代码现象的主要原因和原因是什么

#include <stdio.h>

int main(void)
{
  int a=30, b=16;
  double divresult;
  divresult = a/b;  
  printf("result1 : %f \n", a/b);
  printf("result1 : %f \n", a/b);
  printf("result1 : %f \n", a/b);
  printf("result1 : %f \n", a/b);
  printf("result1 : %f \n", a/b);
  printf("result1 : %f \n", a/b);
  printf("result1 : %f \n", a/b);
  printf("result1 : %f \n", a/b);
  printf("result1 : %f \n", a/b);
  printf("divresult : %f \n",divresult);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  return 0;
}

这里输出

result1 : 0.000000 
result1 : 0.000000 
result1 : 0.000000 
result1 : 0.000000 
result1 : 0.000000 
result1 : 0.000000 
result1 : 0.000000 
result1 : 0.000000 
result1 : 0.000000 
divresult : 1.000000 
result2 : 1.000000 
result2 : 1.000000 
result2 : 1.000000 
result2 : 1.000000 
result2 : 1.000000 
result2 : 1.000000 
result2 : 1.000000 
result2 : 1.000000 
result2 : 1.000000 
result2 : 1.000000 
result2 : 1.000000 
result2 : 1.000000 
result2 : 1.000000 

为什么会这样?我真的无法理解。一般来说,我们知道计算机不能准确表示浮点数。但在这种情况下,似乎存在某种规律。 "divresult printf"前后值的变化是怎么出现的?

Printf 应该打印双精度,但您传递的是整数。这是未定义的行为。在这种情况下,它通过打印先前传递的参数的“remains”来表达自己。在此修改示例中,它清晰可见。但当然它是一个 UB,程序的行为可以完全不同。还要记住,整数除法的结果也是一个整数。 C 和 C++ 中的 30/16 == 1

(double)(a/b) 是 1.0,因为它将整数除法的结果转换为 double

(double)a/ba 转换为双精度,然后进行双除法。

#include <stdio.h>

int main(void)
{
  int a=30, b=16;
  double divresult;
  divresult = a/b;  
  printf("result1 : %f \n", (double)(a/b));
  printf("result1 : %f \n", a/b);
  printf("result1 : %f \n", a/b);
  printf("result1 : %f \n", (double)a/b);
  printf("result1 : %f \n", a/b);
  printf("result1 : %f \n", a/b);
  printf("result1 : %f \n", a/b);
  printf("result1 : %f \n", a/b);
  printf("result1 : %f \n", a/b);
  printf("divresult : %f \n",divresult);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", 0.0);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", (double)a/b);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", (double)(a/b));
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", 0.0);
  printf("result2 : %f \n", a/b);
  printf("result2 : %f \n", a/b);
  return 0;
}

结果

x86-64 gcc 10.2

Program returned: 0
Program stdout

result1 : 1.000000 
result1 : 1.000000 
result1 : 1.000000 
result1 : 1.875000 
result1 : 1.875000 
result1 : 1.875000 
result1 : 1.875000 
result1 : 1.875000 
result1 : 1.875000 
divresult : 1.000000 
result2 : 1.000000 
result2 : 1.000000 
result2 : 0.000000 
result2 : 0.000000 
result2 : 0.000000 
result2 : 1.875000 
result2 : 1.875000 
result2 : 1.875000 
result2 : 1.875000 
result2 : 1.000000 
result2 : 1.000000 
result2 : 1.000000 
result2 : 0.000000 
result2 : 0.000000 
result2 : 0.000000