NAN 和 INFINITY 可以在非默认舍入模式下使用吗?
Can NAN and INFINITY be used under non-default rounding modes?
示例代码:
#include <stdio.h>
#include <math.h>
#include <fenv.h>
#if _MSC_VER && ! __clang__ && ! __INTEL_COMPILER
#pragma fenv_access (on)
#else
#pragma STDC FENV_ACCESS ON
#endif
int main(void)
{
float f;
if (fesetround(RM) != 0) return 1;
f = V;
printf("%f\n", f);
return 0;
}
调用:
$ gcc t583.c -std=c11 -pedantic -Wall -Wextra -DV=NAN -DRM=FE_TOWARDZERO && ./a.exe
nan
$ gcc t583.c -std=c11 -pedantic -Wall -Wextra -DV=INFINITY -DRM=FE_TOWARDZERO && ./a.exe
inf
$ cl t583.c /std:c11 /Za /fp:strict /DV=NAN /DRM=FE_TOWARDZERO /nologo && ./t583.exe
0.000000
$ cl t583.c /std:c11 /Za /fp:strict /DV=INFINITY /DRM=FE_TOWARDZERO /nologo && ./t583.exe
340282346638528859811704183484516925440.000000
GCC 将 NAN
和 INFINITY
定义为:
#define NAN (__builtin_nanf(""))
#define INFINITY (__builtin_inff())
而 MSVC 将 NAN
和 INFINITY
定义为:
#define NAN ((float)(INFINITY * 0.0F))
#define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF))
和_HUGE_ENUF
为:
#define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow
因此,MSVC 在 /fp:strict
和 FE_TOWARDZERO
和 FE_DOWNWARD
下:
INFINITY
的计算结果为 FLT_MAX
,并且
NAN
的计算结果为 0.0
。
困惑。
但是,是否允许在非默认舍入模式下使用NAN
和INFINITY
,例如FE_TOWARDZERO
和FE_DOWNWARD
?
提问原因:更好的理解C标准
正在解决什么问题:使用 MSVC 试验非默认舍入模式,尝试产生预期结果。
更新。微软的回答:
Thanks for reporting this and help us improve our libraries. This issue has been fixed and will be available in a future update.
is it allowed at all to use NAN
and INFINITY
under non-default rounding modes, such as FE_TOWARDZERO
and FE_DOWNWARD
?
语言规范未对使用 INFINITY
表示任何限制。因此,符合规范的实现必须接受它并根据语言规范的规定一致地解释它,而不管舍入模式如何。具体来说,它
expands to a constant expression of type float
representing positive
or unsigned infinity, if available; else to a positive constant of
type float
that overflows at translation time.
(C17 7.12/4)
这不以在任何特定时间有效的舍入模式为条件。由于 MSVC 确实有可用的 float
表示无穷大并且 FLT_MAX
需要表示 finite 数字,因此它不符合 INFINITY
在任何情况下都等于 MSVC 中的 FLT_MAX
。事实上,MSVC 在任何程度上都不符合 INFINITY
从未评估为正 float
无穷大。
NAN
就更清楚了。规范说它
is defined if and only if the implementation supports quiet NaNs for the float type
.
那样的话,
It expands to a constant expression of type float
representing a quiet NaN.
(C17 7.12/5)
如果完全定义了 NAN
,那么它会扩展为计算结果为安静 NaN 的表达式。时期。如果 MSVC 提供了它扩展为 0.0 的情况,那么在这些情况下 MSVC 是不符合要求的。
应该承认,大多数(如果不是全部的话)C 实现都有一些不一致之处,无论是默认情况下还是通过命令行选项或类似方式访问。然而,MSVC 因其在广泛使用的 C 实现中相对较差的一致性而臭名昭著。
示例代码:
#include <stdio.h>
#include <math.h>
#include <fenv.h>
#if _MSC_VER && ! __clang__ && ! __INTEL_COMPILER
#pragma fenv_access (on)
#else
#pragma STDC FENV_ACCESS ON
#endif
int main(void)
{
float f;
if (fesetround(RM) != 0) return 1;
f = V;
printf("%f\n", f);
return 0;
}
调用:
$ gcc t583.c -std=c11 -pedantic -Wall -Wextra -DV=NAN -DRM=FE_TOWARDZERO && ./a.exe
nan
$ gcc t583.c -std=c11 -pedantic -Wall -Wextra -DV=INFINITY -DRM=FE_TOWARDZERO && ./a.exe
inf
$ cl t583.c /std:c11 /Za /fp:strict /DV=NAN /DRM=FE_TOWARDZERO /nologo && ./t583.exe
0.000000
$ cl t583.c /std:c11 /Za /fp:strict /DV=INFINITY /DRM=FE_TOWARDZERO /nologo && ./t583.exe
340282346638528859811704183484516925440.000000
GCC 将 NAN
和 INFINITY
定义为:
#define NAN (__builtin_nanf(""))
#define INFINITY (__builtin_inff())
而 MSVC 将 NAN
和 INFINITY
定义为:
#define NAN ((float)(INFINITY * 0.0F))
#define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF))
和_HUGE_ENUF
为:
#define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow
因此,MSVC 在 /fp:strict
和 FE_TOWARDZERO
和 FE_DOWNWARD
下:
INFINITY
的计算结果为FLT_MAX
,并且NAN
的计算结果为0.0
。
困惑。
但是,是否允许在非默认舍入模式下使用NAN
和INFINITY
,例如FE_TOWARDZERO
和FE_DOWNWARD
?
提问原因:更好的理解C标准
正在解决什么问题:使用 MSVC 试验非默认舍入模式,尝试产生预期结果。
更新。微软的回答:
Thanks for reporting this and help us improve our libraries. This issue has been fixed and will be available in a future update.
is it allowed at all to use
NAN
andINFINITY
under non-default rounding modes, such asFE_TOWARDZERO
andFE_DOWNWARD
?
语言规范未对使用 INFINITY
表示任何限制。因此,符合规范的实现必须接受它并根据语言规范的规定一致地解释它,而不管舍入模式如何。具体来说,它
expands to a constant expression of type
float
representing positive or unsigned infinity, if available; else to a positive constant of typefloat
that overflows at translation time.
(C17 7.12/4)
这不以在任何特定时间有效的舍入模式为条件。由于 MSVC 确实有可用的 float
表示无穷大并且 FLT_MAX
需要表示 finite 数字,因此它不符合 INFINITY
在任何情况下都等于 MSVC 中的 FLT_MAX
。事实上,MSVC 在任何程度上都不符合 INFINITY
从未评估为正 float
无穷大。
NAN
就更清楚了。规范说它
is defined if and only if the implementation supports quiet NaNs for the
float type
.
那样的话,
It expands to a constant expression of type
float
representing a quiet NaN.
(C17 7.12/5)
如果完全定义了 NAN
,那么它会扩展为计算结果为安静 NaN 的表达式。时期。如果 MSVC 提供了它扩展为 0.0 的情况,那么在这些情况下 MSVC 是不符合要求的。
应该承认,大多数(如果不是全部的话)C 实现都有一些不一致之处,无论是默认情况下还是通过命令行选项或类似方式访问。然而,MSVC 因其在广泛使用的 C 实现中相对较差的一致性而臭名昭著。