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是不是舍入浮点常量的主要内容,如果未能解决你的问题,请参考以下文章