NAN
来自的宏math.h
是安静的 NAN:
ISO/IEC 9899:2011 (E)(强调):
宏
南
当且仅当实现支持浮点类型的安静 NaN 时才定义。它扩展为表示安静 NaN的 float 类型的常量表达式。
安静的 NaN 通常不会导致引发 FP 异常。例子:
- ISO/IEC 9899:2011 (E)(强调):
5.2.4.2.2 浮动类型的特点<float.h>
3 一个安静的 NaN在几乎所有算术运算中传播,而不会引发浮点异常;当作为算术操作数出现时,信号 NaN 通常会引发浮点异常。
- IEEE 754-2008(已添加重点):
5.11 比较谓词的细节 明确考虑安静 NaN操作数可能性的程序可以使用表 5.3 中的无序安静谓词,它们不会发出这种无效操作异常的信号。
然而:
llrintf()
既不是算术运算,也不是表 5.3 中的无序安静谓词。因此,5.2.4.2.2.3
和5.11
不适用。7.12.9.5 The lrint and llrint functions
(例如)没有说明如果输入是安静的 NaN 是否引发 FP 异常。
初步结论:由于一般做法“安静的 NaN 不会导致引发 FP 异常”,因此可以得出结论,如果输入是安静的 NaN,则lrint
andllrint
函数不应导致引发 FP 异常。
实践:
代码(t125.c):
#include <fenv.h>
#include <math.h>
#include <stdio.h>
#if _MSC_VER
#pragma fenv_access (on)
#else
#pragma STDC FENV_ACCESS ON
#endif
void show_fe_exceptions(void)
{
printf("exceptions raised: ");
if (fetestexcept(FE_DIVBYZERO)) printf(" FE_DIVBYZERO");
if (fetestexcept(FE_INEXACT)) printf(" FE_INEXACT");
if (fetestexcept(FE_INVALID)) printf(" FE_INVALID");
if (fetestexcept(FE_OVERFLOW)) printf(" FE_OVERFLOW");
if (fetestexcept(FE_UNDERFLOW)) printf(" FE_UNDERFLOW");
if (fetestexcept(FE_ALL_EXCEPT)==0) printf(" none");
printf("\n");
}
int main(void)
{
long long ll;
ll = llrintf(NAN);
show_fe_exceptions();
printf("ll %lld\n", ll);
return 0;
}
调用:
$ cl t125.c /std:c11 /fp:strict && t125
exceptions raised: FE_INEXACT FE_INVALID FE_OVERFLOW
ll 0
$ clang t125.c -std=c11 -ffp-model=strict -Wall -Wextra -pedantic && ./a.exe
t125.c:6:9: warning: unknown pragma ignored [-Wunknown-pragmas]
#pragma fenv_access (on)
^
1 warning generated.
exceptions raised: FE_INEXACT FE_INVALID FE_OVERFLOW
ll -9223372036854775808
$ gcc t125.c -std=c11 -Wall -Wextra -pedantic && ./a.exe
t125.c:8: warning: ignoring ‘#pragma STDC FENV_ACCESS’ [-Wunknown-pragmas]
8 | #pragma STDC FENV_ACCESS ON
|
exceptions raised: FE_INVALID
ll -9223372036854775808
llrintf
问题:如果输入是安静的 NaN ,有人可以澄清围绕 C 标准库函数(例如)引发 FP 异常的情况/行为吗?