【发布时间】:2009-03-16 02:38:38
【问题描述】:
在 C 程序中,当您编写像 3.14159 这样的浮点字面量时,是否存在标准解释,还是依赖于编译器或体系结构? Java 是 exceedingly clear 关于如何解释浮点字符串的,但是当我阅读 K&R 或其他 C 文档时,这个问题似乎已经被掩盖了。
【问题讨论】:
标签: c syntax floating-point
在 C 程序中,当您编写像 3.14159 这样的浮点字面量时,是否存在标准解释,还是依赖于编译器或体系结构? Java 是 exceedingly clear 关于如何解释浮点字符串的,但是当我阅读 K&R 或其他 C 文档时,这个问题似乎已经被掩盖了。
【问题讨论】:
标签: c syntax floating-point
它依赖于架构。 这通常意味着 IEEE 754,但不一定。 C 标准 (ISO 9899:1999) 主要在第 5.2.4.2.2 节“浮动类型的特性”中讨论了这一点。
【讨论】:
来自 C99 标准,第 6.4.4.2 节浮动常量,第 3 段(强调我的):
有效数字部分被解释为(十进制或十六进制)有理数;这 指数部分的数字序列被解释为十进制整数。对于十进制 浮动常数,指数表示有效数部分的 10 次方 要缩放。对于十六进制浮点常量,指数表示 2 的幂 有效数字部分将被缩放。对于十进制浮点常量,也适用于
FLT_RADIX不是 2 的幂时的十六进制浮点常量,结果是 最接近的可表示值,或立即较大或较小的可表示值 与最近的可表示值相邻,以实现定义的方式选择。 对于FLT_RADIX是 2 的幂时的十六进制浮点常量,结果为 正确舍入。
因此,您将以实现定义的方式在一个 ULP 中获得一个常量。回想一下,实现定义意味着实现(在本例中为 C 运行时)可以选择任何选项,但该选择必须记录在案。因此,您可以查阅 libc 运行时文档以了解舍入是如何发生的。
【讨论】:
您不清楚您的意思是浮点文字作为源代码的一部分(供编译器解析为依赖于架构的二进制表示),还是由库函数扫描,例如scanf()、atof()、@ 987654323@、strtod() 和 strtold()(在运行时,转换为内存中的 float、double 或 long double 值)。
在第一种情况下,它是 ISO/IEC 9899:1999 (ISO C99) 第 6.4.4.2 节“浮动常量”的一部分。它定义了词典和它的解释方式。
在第二种情况下,库函数的行为在第 7.20.1 节“数值转换函数”中定义。
我没有以前标准(ANSI C,1989)的硬拷贝,但我很确定它也非常精确地定义了浮点数的解析和转换方式。
如果您想知道在内存中是否存在以二进制格式表示这些值的标准,答案是否定的。 C 语言旨在接近架构,而不是对其施加约束。所以内存中的表示总是依赖于架构的。但是 C 标准定义了如何对浮点值执行算术运算。它遵循 IEC 60559 标准。在 ISO C99 标准中,在附录 F(规范性)“IEC 60559 浮点运算”中对其进行了描述。实施可能会或可能不会实施本标准。如果是,则必须定义 __STDC_IEC_559__ 预处理器名称。
【讨论】: