【问题标题】:Does C round floating-point constantsC是否舍入浮点常量
【发布时间】:2014-03-12 00:35:51
【问题描述】:

A question about floating-point precision in Go 让我想知道 C 是如何处理这个问题的。

在 C 中使用以下代码:

float a = 0.1;

a 是否具有最接近的 IEEE 754 二进制表示:

00111101110011001100110011001101 (Decimal:  0.10000000149011612)

还是将其裁剪为:

00111101110011001100110011001100 (Decimal:  0.09999999403953552)

还是会因编译器/平台而异?

【问题讨论】:

    标签: c floating-point floating-point-precision


    【解决方案1】:

    一个实现被允许做任何一个(或者甚至是多一个):

    对于十进制浮点常量,以及当 FLT_RADIX 不是 2 的幂时的十六进制浮点常量,结果要么是最接近的可表示值,要么是紧邻最接近的可表示值的较大或较小的可表示值,在实现定义的方式。

    (C11,§6.4.4.2/3)

    自 C99 以来,我们已经有了十六进制浮点常量,以便您可以精确指定所需的位(假设实现提供二进制浮点 :)),因此您可以说,例如:

    float a = 0x1.99999Ap-4;
    

    对于 IEEE 754 32 位浮点数:

    #include <stdio.h>
    int main() {
      float a = 0.1;
      float low  = 0x0.1999999p0;
      float best = 0x0.199999ap0;
      float high = 0x0.199999bp0;
      printf("a is %.6a or %.16f, which is either %.16f, %.16f or %.16f\n",
              a, a, low, best, high);
      return 0;
    }
    

    【讨论】:

    • 我不知道 C11 标准的复制成本那么高。我也不知道十六进制浮点数。谢谢!嗯..但我想知道为什么有人会否决答案。
    • @ANisus:您可以免费下载与 C11 标准非常相似的东西。见stackoverflow.com/questions/81656/…
    • 理论上它依赖于编译器,但实际上,它会四舍五入到最接近的值:大多数实现都遵循其他标准,如 IEEE-754 或 ISO 10967(至少部分)
    • @aka.nice:正确舍入很困难。并非所有实现都需要精确(但它们应该设法满足稍微宽松的标准)。例如,请参阅exploringbinary.com/…
    • @rici 我知道这有多么困难,尤其是要有效地做到这一点,但是很多其他事情都很难 w.r.t.到 IEEE 754(即尝试实现一些具有单调性或最大误差约束的数学函数),所以除了一些奇异的硬件情况外,依靠最先进的 libc 是一个很好且容易的开始。
    【解决方案2】:

    标准未指定,但在某些本地硬件上进行测试:

    #include <stdio.h>
    
    int
    main( int argc, char **argv )
    {
    float   a = 0.1;
    double  b = a;
    
    printf("%.16f\n", b );
    }
    

    0.1000000014901161

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-09
      • 2015-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-11
      • 1970-01-01
      相关资源
      最近更新 更多