为什么很少使用浮点数的十六进制表示?
像这样写是不是0x0.01
有助于避免一些意外,比如 0.01 突然变成0.010000000000
什么东西?
小数 pi 应该多长才能精确?
似乎有这个指令 FLDPI,它将 pi 加载到协处理器中,为什么你必须在代码中编写 pi?手臂有相同的指令吗?
为什么很少使用浮点数的十六进制表示?
像这样写是不是0x0.01
有助于避免一些意外,比如 0.01 突然变成0.010000000000
什么东西?
小数 pi 应该多长才能精确?
似乎有这个指令 FLDPI,它将 pi 加载到协处理器中,为什么你必须在代码中编写 pi?手臂有相同的指令吗?
我一直使用 C99 的十六进制表示法来表示浮点数,无论是输入还是输出。
使用十进制格式 D.DDDDDDDDDDDDDDDDDDEXXX(小数点后的 16 位数字)保证符号唯一标识任何double
,包括最接近 π 的双精度。
像 C 这样的语言旨在具有可移植性,不应依赖于特定指令集的功能。旧的 80 位浮点指令也非常过时,尽管它们对于显式使用 80 位计算的程序仍然有用long double
。在 π 的特殊情况下,3.141592653589793
是得到正确的最小十进制表示double
。另外,请注意,FLDPI
当程序中的常量恰好是指令将加载的常量时,编译器总是可以生成指令。然而,同样,80 位 FPU 已经过时,只能由现代编译器用于 long double 计算。经过测试,GCC 和 Clang 都不会生成FLDPI
指令,即使移动0x3.243F6A8885A308D313198A2E03707344
到long double
. 蹩脚......我几乎想填写一份错误报告。
0x
和p
标记对于避免整数表示法的歧义是必要的。在十六进制中,它非常简单:每个十六进制数字代表 4 位,普通双精度的形式为 1.<52 个二进制数字>。因此,后面正好有 13 个十六进制数字1.
是有效的。在十进制中,最多需要 16 位数字才能识别double
. 要自己观察这一点,请执行:
#include <stdio.h>
#include <math.h>
…
printf("%.16e\n%.16e\n", 1.0, nextafter(1.0, 2.0));
看到更少的数字会引起混乱。
好的,关于“π 应该多长”的问题。这些功能:
int main (void){printf("%.80f\n\n", 0x3.243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98p0 );}
int main (void){printf("%.80f\n\n", 3.14159265358979323846264338327950288419716939937510582097494459 );}
int main (void){printf("%.80f\n\n", 3.141592653589793 );}
打印完全相同的数字:
3.14159265358979311599796346854418516159057617187500000000000000000000000000000000
如果它变得更短,结果会有所不同。
考虑一下您在日常生活中的经历:您是否处理并遇到十进制实数或指定为任何其他基数的实数?
您仍然会感到惊讶,因为无论如何都会发生浮点值计算中的舍入和近似错误。