C是不是舍入浮点常量

Posted

技术标签:

【中文标题】C是不是舍入浮点常量【英文标题】: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)

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

【问题讨论】:

【参考方案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 标准非常相似的东西。见***.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

【讨论】:

以上是关于C是不是舍入浮点常量的主要内容,如果未能解决你的问题,请参考以下文章

常量与数据类型

C中的十六进制浮点常量

java知识点拾遗(基本语法)

不精确浮点常量的警告

程序C语言中基本数据类型(字符、整数、长整数、浮点)

c复习过程随笔二