为了避免在库代码中引发 `FE_INEXACT`,我应该走多远?

To what lengths should I go in order to avoid raising `FE_INEXACT` in library code?

我正在用 C 语言创建一个库,其中包含用于一般用途的通用数据结构、便利函数等。在其中,我实现了一个动态数组,并且我选择黄金比例作为增长因子,原因已解释 here。但是,这必然涉及浮点数的乘法运算,如果有效数很大,可能会导致 FE_INEXACT 增加。

当我实现它时,我的印象是,由于该库是通用的,因此必须尽可能避免出现浮点异常。我首先尝试了类似

fenv_t fenv;
feholdexcept(&fenv);
// expand dynamic array
feclearexcept(FE_INEXACT);
feupdateenv(&fenv);

,但这花费了如此巨大的时间成本,不值得。

最终,我想出了一个时间成本可以忽略不计的解决方案。虽然没有完全避免 FE_INEXACT,但它使它变得极不可能。即,

size_t newCapacity = nearbyint((double)(float)PHI * capacity);

如果当前容量非常大,这只会引发 FE_INEXACT,至少对于遵守 IEEE 754 标准的编译器而言。

我开始怀疑我的努力是否解决了一个相对无关紧要的问题。对于库代码,期望用户在必要时处理 FE_INEXACT 的提升是否合理,还是应该在库内避免?在后一种情况下,与效率等其他因素相比,该问题有多重要?

To what lengths should I go...

None 完全没有。几乎没有人使用 fenv.h,编译器甚至不完全支持它(它们进行的转换错误地忽略或改变了浮点环境),如果调用您的代码的人正在使用它,那么要求他们 save/restore 调用您的库的异常状态。此外,大多数情况下,如果您正在执行引发 FE_INEXACT 的操作,那是 正是因为 您将要返回的结果是不准确的,因此在语义上适合养。