更改浮点舍入模式

jef*_*yer 40 c c++ floating-point x86

更改IEEE 754浮点数的舍入模式*的最有效方法是什么?便携式C函数会很好,但使用x86程序集的解决方案也可以.

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

Ste*_*non 38

这是标准的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);
Run Code Online (Sandbox Code Playgroud)

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

编辑 您不需要求助于MSVC的程序集.您可以使用(完全非标准)_controlfp( ):

unsigned int originalRounding = _controlfp(0, 0);
_controlfp(_RC_CHOP, _MCW_RC);
// do something ...
_controlfp(originalRounding, _MCW_RC);
Run Code Online (Sandbox Code Playgroud)

您可以在MSDN上阅读有关_controlfp()的更多信息.

而且,为了完整性,一个用于舍入模式的宏名称的解码器环:

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
Run Code Online (Sandbox Code Playgroud)

  • 从技术上讲,这需要`#pragma STDC FENV_ACCESS ON`才能工作,尽管大多数编译器都会这样做,所以它"通常"没有它,并忽略`#pragma` ... (3认同)
  • 为了完整性:x86上的"最近"是"最近的",以防有人想知道. (3认同)
  • @Pod:如果我们要迂腐,那就让我们做对."舍入到最近,连接到均匀"是所有符合IEEE-754标准的系统的默认舍入模式. (3认同)