我正在尝试编写constexpr
函数的exp
版本。我知道
FE_TONEAREST
舍入fesetround( int round )
更改舍入模式(前提是支持#pragma STDC FENV_ACCESS
且设置为ON
)fesetround(int)
函数中调用非constexpr函数constexpr
如果我的理解是正确的,这意味着(在支持#pragma STDC FENV_ACCESS
的编译器中),允许用户在调用我的函数之前设置舍入模式,但是我的函数不会被允许做这个改变(甚至是暂时的),因此可以用错误的舍入模式来执行。
我可以提出处理此问题的最佳选择是拥有两个功能:
constexpr
,未设置舍入模式constexpr
并执行以下操作:
FE_TONEAREST
要设置一个constexpr
变量,必须调用版本A,但总是会评估,因为舍入模式为FE_TONEAREST
,因为(根据cppreference):< / p>
当前的舍入模式不会影响....的结果 常量表达式中的浮点算术运算符(总是为 最近的)
在非constexpr contexts
中,只要舍入模式为FE_TONEAREST
,版本A和版本B就会同意,但版本B将为任何其他舍入模式提供更好的结果。用户有责任使用FE_TONEAREST
四舍五入或确保调用版本B.
在标准C ++中是否有更好的方法来处理这个问题? ...或者该标准是否还有其他关于舍入模式的事情,这使得整个问题没有实际意义?
修改:我的目标是尊重舍入模式; 忽略,以便功能的准确性保持一致。我更愿意只使用版本B,但无法在constexpr
函数中更改舍入模式。
答案 0 :(得分:1)
C和C ++提供的FENV_ACCESS
功能是一个kludge,并不支持在这个问题中寻求使用。修改舍入模式的程序很少,并且对它们的语言支持很差。
根据C标准(并通过引用由C ++继承),FENV_ACCESS
通知实现程序可能在非默认浮点控制模式下运行。如果您允许在非默认模式下调用exp
函数并且未使用FENV_ACCESS
进行翻译,则标准不会告诉我们行为将是什么。
此外,C ++没有提供任何方法来根据舍入模式或FENV_ACCESS
的状态自动调用不同版本的例程(尽管C ++实现可能会作为语言的扩展)
从cppreference引用的语句,舍入模式不会影响常量表达式中的算术运算,这似乎是由cppreference派生的结论,而不是C ++标准中明确规定的结果。也许这是因为在转换时评估常量表达式,因此不能对浮点环境进行任何修改。但是,我不清楚这是否完全由标准保证 - expr.const部分中的注释说“在翻译期间可以评估常量表达式。”并不是说它们必须在翻译期间进行评估。
通常,当舍入模式最接近无限或其他设置时,人们不希望exp
的行为方式相同。相反,当模式朝向无穷大时,人们希望exp
返回向上舍入的结果,当模式朝向负无穷大时,需要向下舍入,当模式朝向零时,则向下舍入为零。 (获得这些结果需要为每种模式设置exp
的不同实现,因为仅对每个操作应用舍入不会产生所需的结果。)因此,exp
返回相同结果的请求无论如何舍入模式有点不寻常。当程序使用不同的舍入模式评估浮点运算时,它有什么作用来返回舍入到最接近的结果?如果程序使用朝向无穷大来尝试计算上限,则最接近的exp
会破坏该计算。