【问题标题】:Change floating point rounding mode更改浮点舍入模式
【发布时间】:2011-10-15 14:40:42
【问题描述】:

更改 IEEE 754 浮点数的舍入模式* 最有效的方法是什么?一个可移植的 C 函数会很好,但是使用 x86 汇编的解决方案也可以。

*我指的是向最近、向零和向正/负无穷大的标准舍入模式

【问题讨论】:

  • 请更详细地描述您希望的舍入模式更改。其中有些不涉及 FPU 标志,有些则涉及。
  • AFAICT,它们都涉及 x87 FPU 标志,即 RM 位。向最近 = 00(二进制),向 -infinity 是 01,向 +infinity 是 10,向零 = 11。

标签: c++ c floating-point x86


【解决方案1】:

这是标准的 C 解决方案:

#include <fenv.h>
#pragma STDC FENV_ACCESS ON

// store the original rounding mode
const int originalRounding = fegetround( );
// establish the desired rounding mode
fesetround(FE_TOWARDZERO);
// do whatever you need to do ...

// ... and restore the original mode afterwards
fesetround(originalRounding);

在缺乏 C99 支持的向后平台上,您可能需要求助于汇编。在这种情况下,您可能需要为 x87 单元(通过 fldcw 指令)和 SSE(通过 ldmxcsr 指令)设置舍入。

编辑 您不需要为 MSVC 求助于汇编。您可以改用(完全非标准的)_controlfp( )

unsigned int originalRounding = _controlfp(0, 0);
_controlfp(_RC_CHOP, _MCW_RC);
// do something ...
_controlfp(originalRounding, _MCW_RC);

您可以阅读有关 _controlfp( ) on MSDN 的更多信息。

为了完整起见,还有一个用于舍入模式的宏名称的解码器环:

rounding mode    C name         MSVC name
-----------------------------------------
to nearest       FE_TONEAREST   _RC_NEAR
toward zero      FE_TOWARDZERO  _RC_CHOP
to +infinity     FE_UPWARD      _RC_UP
to -infinity     FE_DOWNWARD    _RC_DOWN

【讨论】:

  • 从技术上讲,这需要#pragma STDC FENV_ACCESS ON 才能工作,尽管大多数编译器都会这样做,因此它“通常”在没有它的情况下也能工作,并忽略#pragma...
  • 为了完整性:x86 上的“最近”是“最近的偶数”,以防有人想知道。
  • @Pod:如果我们要学究气,那就做对吧。 “四舍五入,与偶数相等”是所有符合 IEEE-754 的系统的默认舍入模式。
  • MSVC 不应该是_controlfp 吗?
  • 我试图自己编辑它,但被网站阻止了,因为修复所有事件只会导致 6 个更改的字符,当一个人编辑某人时必须更改至少 10 个字符-否则发布,否则无法编辑。由于我发现除了达到字符限制之外无缘无故更改您帖子中的其他内容是不合适的,因此我得出结论,要求您编辑您的帖子对我来说是最好的做法。
【解决方案2】:

this 可能会有所帮助。

编辑:我会说您需要自己的功能。您可以在 C 中使用汇编。

但如果您的寄存器大小是 64 位,则将其四舍五入到 32 位会使您的计算速度更快。它实际上会使它变慢。请记住,对于 64 位微处理器而不是 2-32 位,64 位计算很容易。我不知道你到底想达到什么。我知道性能取决于您的标准。

【讨论】:

  • 这看起来像是将事物四舍五入为整数。我正在寻找一种方法来更改舍入到最近的机器可表示数字的方式。
  • 我认为您回答的问题与 OP 的问题略有不同。虽然您可以使用这些(连同缩放函数)对结果进行任意舍入,但这比设置舍入模式要痛苦得多且速度慢。
  • 我认为您必须为此编写自己的函数。您可以在 c 中使用汇编。这将是一个高效的功能
  • 仅链接答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-29
  • 2015-03-23
  • 2015-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多