main()
{
int z;
float b=3.1;
z=b*5+1.5;
printf("%d",z);
}
我得到的 z 值为 16。
当我使用 double 时,我得到 17。为什么会这样?
最佳答案
鉴于浮点通常使用二进制浮点编码,因此许多数字(例如 3.1)float/double
无法精确编码。 **1 在 OP 的例子中,不是将 3.1 精确地保存在 b
中,而是保存了附近的值。对于 float
和 double
,使用了不同的近似值,得出了 16 与 17。
FP 数学和 int
截断的结果强调了这种差异。
#include <float.h>
#include <stdio.h>
int main(void) {
printf("%d\n",FLT_EVAL_METHOD);
float b=3.1;
printf("%.20f %.20f %d\n",b, b*5+1.5, (int) (b*5+1.5));
volatile float v=3.1;
printf("%.20f %.20f %d\n",v, v*5+1.5, (int) (v*5+1.5));
double d=3.1;
printf("%.20f %.20f %d\n",d, d*5+1.5, (int) (d*5+1.5));
}
输出
2
3.09999990463256835938 16.99999952316284179688 16
3.09999990463256835938 16.99999952316284179688 16
3.10000000000000008882 17.00000000000000000000 17
<小时/>
有时,FLT_EVAL_METHOD
的效果允许进行一些浮点
数学运算,而 double
数学运算会使情况变得复杂。因此,上面使用了 volatile float
来帮助其他人尝试对此代码的变体。
提示:如果有大量警告,代码可能会收到如下警告。这暗示 3.1
和 3.1f
不同。
// warning: conversion to 'float' alters 'double' constant value [-Wfloat-conversion]
float b=3.1;
// no warning
float b=3.1f;
<小时/>
作为直接将 FP 值分配给 int
的替代方法,请考虑各种舍入函数,例如 round()、roundf()、appearance()、rint()、lrint( )
等
#include <math.h>
// example: float to long
long int lrintf(float x);
long long_var = lrintf(float_var);
<小时/>
**1 数字有无限多个。但只有大约 232 个不同的 float
。
关于c - float 和 double 精度位数的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46893183/