我想在目标板上测试以下内容:
'float'是用IEEE 754单精度(32位)浮点变量实现的吗?
'double'是用IEEE 754双精度(64位)浮点变量实现的吗?
有什么方法可以用简单的C程序测试它 .
没有简单的测试 .
今天绝大多数系统都使用IEEE-754格式进行浮点运算 . 但是,大多数C实现不完全符合IEEE 754(与IEC 60559相同),并且不设置预处理器标识符 __STDC_IEC_559__ . 在没有此标识符的情况下,确定C实现是否符合IEEE 754的唯一方法是以下一种或组合:
__STDC_IEC_559__
阅读其文档 .
检查其源代码 .
测试它(当然,当只有详尽的测试可以确定时,这是困难的) .
在许多C实现和软件应用程序中,可以忽略或解决与IEEE 754的偏差:您可以编写代码,就像IEEE 754正在使用中一样,而且很多代码将在很大程度上起作用 . 然而,有许多事情可能使一个毫无戒心的程序员绊倒;即使遵守完整规范,写入完全正确的浮点代码也很困难 .
常见偏差包括:
中间算术的执行精度高于标称类型 . 例如,使用 double 值的表达式可以用 long double precision计算 .
double
long double
sqrt 在每种情况下都不会返回正确的舍入值 .
sqrt
其他数学库例程从正确舍入的结果返回可能略微偏离(几个ULP)的值 . (事实上,没有人实现IEEE 754-2008中推荐的所有数学例程,同时保证了正确的舍入和保证绑定运行时间 . )
次正规数(浮点格式边缘附近的微小数字)可以转换为零,而不是按照IEEE 754的规定进行处理 .
十进制数字(例如,源代码中的 3.1415926535897932384626433 )和二进制浮点格式(例如,通用 double 格式,IEEE-754 64位二进制)之间的转换在任一转换方向上并不总是正确地舍入 .
3.1415926535897932384626433
仅支持舍入到最近模式;不支持IEEE 754中指定的其他舍入模式 . 或者它们可用于简单算术但需要使用特定于机器的汇编语言来访问 . 标准数学库( cos , log 等等)很少支持其他舍入模式 .
cos
log
在C99中,您可以检查 __STDC_IEC_559__ :
#ifdef __STDC_IEC_559__ /* using IEEE-754 */ #endif
这是因为C99引用的国际浮点标准是IEC 60559:989(IEC 559和IEEE-754是之前的描述) . 从C语言到IEC 60559的映射是可选的,但如果在使用中,实现定义了宏 __STDC_IEC_559__ (C99标准的附录F),因此您可以完全依赖它 .
另一种方法是手动检查 float.h 中的值,例如 FLT_MAX , FLT_EPSILON , FLT_MAX_10_EXP 等是否与IEEE-754限制匹配,尽管理论上可能存在具有相同值的另一种表示 .
float.h
FLT_MAX
FLT_EPSILON
FLT_MAX_10_EXP
首先,您可以在维基百科中找到有关ISO / IEC / IEEE 60559(或IEEE 754)的详细信息:
Floating point standard types
正如F. Goncalvez告诉你的那样,如果符合IEEE 754,宏 __STDC_IEC_559__ 会为您提供有关编译器的信息 .
接下来,我们
但是,您可以使用宏 FLT_EVAL_METHOD 获取其他信息 .
FLT_EVAL_METHOD
此宏的值意味着:
0所有操作和常量都在所用类型的范围和精度中进行评估 .
1类型 float 和 double 的操作在 double 的范围和精度中进行评估, long double 以您自己的方式进行...
float
2所有类型的评估均以 long double 的精度和范围完成 .
-1不确定
其他负值:实现定义(取决于您的编译器) .
例如,如果 FLT_EVAL_METHOD == 2 ,并且您在浮点变量 x 中保存了多个计算的结果,则所有操作和常量都以最佳预算计算或处理,即 long double ,但只有最终结果舍入到该类型 x 有 .
FLT_EVAL_METHOD == 2
x
这种行为减少了数字错误的影响 .
为了要了解有关浮点类型的详细信息,您必须查看标准头 <float.h> 提供的常量宏 .例如,请看这个链接:
<float.h>
Çharacteristics of floating point types
在您的实现不符合IEEE 754标准的可悲情况下,您可以尝试在标准头 <float.h> 中查找详细信息(如果存在) .此外,您还必须阅读编译器的文档 .
例如,编译器GCC解释了浮点数的作用:
Stadus of C99 features in GCC
3 回答
没有简单的测试 .
今天绝大多数系统都使用IEEE-754格式进行浮点运算 . 但是,大多数C实现不完全符合IEEE 754(与IEC 60559相同),并且不设置预处理器标识符
__STDC_IEC_559__
. 在没有此标识符的情况下,确定C实现是否符合IEEE 754的唯一方法是以下一种或组合:阅读其文档 .
检查其源代码 .
测试它(当然,当只有详尽的测试可以确定时,这是困难的) .
在许多C实现和软件应用程序中,可以忽略或解决与IEEE 754的偏差:您可以编写代码,就像IEEE 754正在使用中一样,而且很多代码将在很大程度上起作用 . 然而,有许多事情可能使一个毫无戒心的程序员绊倒;即使遵守完整规范,写入完全正确的浮点代码也很困难 .
常见偏差包括:
中间算术的执行精度高于标称类型 . 例如,使用
double
值的表达式可以用long double
precision计算 .sqrt
在每种情况下都不会返回正确的舍入值 .其他数学库例程从正确舍入的结果返回可能略微偏离(几个ULP)的值 . (事实上,没有人实现IEEE 754-2008中推荐的所有数学例程,同时保证了正确的舍入和保证绑定运行时间 . )
次正规数(浮点格式边缘附近的微小数字)可以转换为零,而不是按照IEEE 754的规定进行处理 .
十进制数字(例如,源代码中的
3.1415926535897932384626433
)和二进制浮点格式(例如,通用double
格式,IEEE-754 64位二进制)之间的转换在任一转换方向上并不总是正确地舍入 .仅支持舍入到最近模式;不支持IEEE 754中指定的其他舍入模式 . 或者它们可用于简单算术但需要使用特定于机器的汇编语言来访问 . 标准数学库(
cos
,log
等等)很少支持其他舍入模式 .在C99中,您可以检查
__STDC_IEC_559__
:这是因为C99引用的国际浮点标准是IEC 60559:989(IEC 559和IEEE-754是之前的描述) . 从C语言到IEC 60559的映射是可选的,但如果在使用中,实现定义了宏
__STDC_IEC_559__
(C99标准的附录F),因此您可以完全依赖它 .另一种方法是手动检查
float.h
中的值,例如FLT_MAX
,FLT_EPSILON
,FLT_MAX_10_EXP
等是否与IEEE-754限制匹配,尽管理论上可能存在具有相同值的另一种表示 .首先,您可以在维基百科中找到有关ISO / IEC / IEEE 60559(或IEEE 754)的详细信息:
Floating point standard types
正如F. Goncalvez告诉你的那样,如果符合IEEE 754,宏
__STDC_IEC_559__
会为您提供有关编译器的信息 .接下来,我们
但是,您可以使用宏
FLT_EVAL_METHOD
获取其他信息 .此宏的值意味着:
0所有操作和常量都在所用类型的范围和精度中进行评估 .
1类型
float
和double
的操作在double
的范围和精度中进行评估,long double
以您自己的方式进行...2所有类型的评估均以
long double
的精度和范围完成 .-1不确定
其他负值:实现定义(取决于您的编译器) .
例如,如果
FLT_EVAL_METHOD == 2
,并且您在浮点变量x
中保存了多个计算的结果,则所有操作和常量都以最佳预算计算或处理,即long double
,但只有最终结果舍入到该类型x
有 .这种行为减少了数字错误的影响 .
为了要了解有关浮点类型的详细信息,您必须查看标准头
<float.h>
提供的常量宏 .例如,请看这个链接:
Çharacteristics of floating point types
在您的实现不符合IEEE 754标准的可悲情况下,您可以尝试在标准头
<float.h>
中查找详细信息(如果存在) .此外,您还必须阅读编译器的文档 .
例如,编译器GCC解释了浮点数的作用:
Stadus of C99 features in GCC