Dar*_*tom 9 c floating-point precision long-double unions
考虑以下程序:
#include <stdio.h>
union myUnion
{
int x;
long double y;
};
int main()
{
union myUnion a;
a.x = 5;
a.y = 3.2;
printf("%d\n%.2Lf", a.x, a.y);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
-858993459
3.20
Run Code Online (Sandbox Code Playgroud)
很好,因为该int成员使用该成员的某些位进行解释long double。但是,相反实际上并不适用:
#include <stdio.h>
union myUnion
{
int x;
long double y;
};
int main()
{
union myUnion a;
a.y = 3.2;
a.x = 5;
printf("%d\n%.2Lf", a.x, a.y);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
5
3.20
Run Code Online (Sandbox Code Playgroud)
问题是,为什么long double不将它们重新解释为某个垃圾值(因为其字节中的4个应表示整数)?这不是巧合,程序针对的所有值输出3.20 a.x,而不仅仅是5。
但是,反向并不真正适用
在小端序系统上(多字节值的最低有效字节在最低地址),int对应于的尾数的最低有效位long double。您必须long double非常精确地打印出来,才能看到它对int那些无关紧要的数字的影响。
在大型字节序系统(如Power PC盒)上,情况会有所不同:该int部分将与的最高有效部分long double对齐,与符号位,指数和最高有效尾数位重叠。因此x,即使只打印了几个有效数字,的变化也会对观察到的浮点值产生巨大影响。但是,对于的较小值x,该值似乎为零。
在PPC64系统上,以下版本的程序:
int main(void)
{
union myUnion a;
a.y = 3.2;
int i;
for (i = 0; i < 1000; i++) {
a.x = i;
printf("%d -- %.2Lf\n", a.x, a.y);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
只打印什么
1 -- 0.0
2 -- 0.0
[...]
999 - 0.0
Run Code Online (Sandbox Code Playgroud)
这是因为我们正在创建一个全零的指数字段,从而使值接近零。但是,初始值3.2完全被破坏了。它不仅仅消除了其最低有效位。
| 归档时间: |
|
| 查看次数: |
125 次 |
| 最近记录: |