gpt4 book ai didi

在打印、转换中考虑 FPU 舍入模式的编译平台

转载 作者:太空狗 更新时间:2023-10-29 15:34:03 25 4
gpt4 key购买 nike

编辑:我在调试 session 期间犯了一个错误,导致我提出这个问题。我看到的差异实际上在于打印 double 和解析 double (strtod)。即使在这次整改之后,斯蒂芬的回答仍然很好地涵盖了我的问题,所以我想我会单独留下这个问题,以防它对某人有用。

我有权访问的一些(大多数)C 编译平台在以下情况下不考虑 FPU 舍入模式

  • 将 64 位整数转换为 double
  • 打印一个double

这里没有什么奇特的东西:Mac OS X Leopard、各种最新的 Linux 和 BSD 变体、Windows。

另一方面,Mac OS X Snow Leopard 在做这两件事时似乎考虑了舍入模式。当然,不同的行为让我无休止地烦恼。

以下是这两种情况的典型片段:

#if defined(__OpenBSD__) || defined(__NetBSD__) 
# include <ieeefp.h>
# define FE_UPWARD FP_RP
# define fesetround(RM) fpsetround(RM)
#else
# include <fenv.h>
#endif

#include <float.h>
#include <math.h>

fesetround(FE_UPWARD);

...
double f;
long long b = 2000000001;
b = b*b;
f = b;

...
printf("%f\n", 0.1);

我的问题是:

  1. 我可以做一些非丑陋的事情来规范所有平台上的行为吗?一些隐藏的设置来告诉平台不考虑舍入模式,反之亦然?
  2. 其中一项行为是否标准?
  3. 不使用 FPU 舍入模式时我可能会遇到什么?向零舍入?四舍五入到最近?请告诉我只有一种选择:)

关于 2。我在标准中找到了一个地方,据说转换为整数的 float 总是被截断(向零四舍五入),但我找不到整数 -> 浮点方向的任何内容。

最佳答案

如果没有设置舍入模式,应该是IEEE-754默认的模式,即round-to-nearest。

对于从整数到 float 的转换,C 标准规定 (§6.3.1.4):

When a value of integer type is converted to a real floating type, if the value being converted can be represented exactly in the new type, it is unchanged. If the value being converted is in the range of values that can be represented but cannot be represented exactly, the result is either the nearest higher or nearest lower representable value, chosen in an implementation-defined manner. If the value being converted is outside the range of values that can be represented, the behavior is undefined.

所以这两种行为都符合C标准。

C 标准规定 (§F.5) IEC60559 浮点格式和字符序列之间的转换应根据 IEEE-754 标准正确舍入。对于非 IEC60559 格式,建议这样做,但不是必需的。 1985 IEEE-754 标准说(第 5.4 条):

Conversions shall be correctly rounded as specified in Section 4 for operands lying within the ranges specified in Table 3. Otherwise, for rounding to nearest, the error in the converted result shall not exceed by more than 0.47 units in the destination's least significant digit the error that is incurred by the rounding specifications of Section 4, provided that exponent over/underflow does not occur. In the directed rounding modes the error shall have the correct sign and shall not exceed 1.47 units in the last place.

第 (4) 节实际上说的是操作应根据流行的舍入模式进行。 IE。如果你改变舍入模式,IEEE-754 说 float->string 转换的结果应该相应地改变。整数-> float 转换也是如此。

IEEE-754 标准的 2008 年修订版说(第 4.3 条):

The rounding-direction attribute affects all computational operations that might be inexact. Inexact numeric floating-point results always have the same sign as the unrounded result.

这两种转换在第 5 条中都被定义为计算操作,因此它们应该再次根据流行的舍入模式执行。

我认为 Snow Leopard 在这里具有正确的行为(假设它正确根据普遍的舍入模式舍入结果)。如果您想强制执行旧行为,我想您总是可以将 printf 调用包装在更改舍入模式的代码中,尽管这显然不理想。

或者,您可以在 C99 兼容平台上使用 %a 格式说明符(十六进制 float )。由于此转换的结果始终是精确的,因此它永远不会受到流行的舍入模式的影响。我认为 Windows C 库不支持 %a,但如果需要,您可以很容易地移植 BSD 或 glibc 实现。

关于在打印、转换中考虑 FPU 舍入模式的编译平台,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2595563/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com