c - float 和 double 精度位数的差异

标签 c floating-point

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 中,而是保存了附近的值。对于 floatdouble,使用了不同的近似值,得出了 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.13.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/

相关文章:

c - memset_s() : What does the standard mean with this piece of text?

c - 理解 C 中的 Float

c - 如何将混合数据类型(int,float,char等)存储在数组中?

c - 需要有非阻塞的命名管道,能够在 Linux 上的 c 中进行双向通信

mysql - Perl/mysql 浮点不精确

php - 如何修复 PhpExcel 额外的小数点错误?

c++ - C++中 float 的限制

c++ - 对 vector <vectors< double>> 进行排序并删除重复项

对 execve 的调用参数太少,但应该接收全部参数

android - FFmpeg mux 视频使用 libavformat avcodec 但无法播放输出