浮点精度是可变的还是不变的?
我不断得到浮点数( float
, double
float
或long double
float
)是否只有一个精度值,或者精度值是否可以变化的混合答案。
一个称为浮点与双精度的主题似乎意味着浮点精度是绝对的。
然而,另一个称为float和double之间的区别的话题是,
通常情况下,double有15到16个十进制数字的精度
另有消息称,
浮点类型的变量通常具有约 7位有效数字的精度
类型double的变量通常具有约 16位有效数字的精度
如果我使用的敏感代码在我的值不精确时很容易中断,我不喜欢引用上述近似值。 所以让我们直接记录。 浮点精度是可变的还是不变的,为什么?
精度是固定的,对于双精度来说精确度为53个二进制数字 (如果我们排除隐含的前导1,则精度为52)。 这出来大约十五位十进制数字 。
OP要求我详细说明为什么只有53个二进制数字意味着“大约”15个十进制数字。
为了直观地理解这一点,我们考虑一个不太精确的浮点格式:而不是像双精度数字那样的52位尾数,我们将使用4位尾数。
因此,每个数字将如下所示:(-1)s×2yyy×1.xxxx(其中s
是符号位, yyy
是指数, 1.xxxx
是标准化尾数)。 对于直接讨论,我们只关注尾数而不是符号或指数。
下面是所有xxxx
值的1.xxxx
样式表(所有舍入为半到平均值,就像默认浮点舍入模式的工作方式一样):
xxxx | 1.xxxx | value | 2dd | 3dd
--------+----------+----------+-------+--------
0000 | 1.0000 | 1.0 | 1.0 | 1.00
0001 | 1.0001 | 1.0625 | 1.1 | 1.06
0010 | 1.0010 | 1.125 | 1.1 | 1.12
0011 | 1.0011 | 1.1875 | 1.2 | 1.19
0100 | 1.0100 | 1.25 | 1.2 | 1.25
0101 | 1.0101 | 1.3125 | 1.3 | 1.31
0110 | 1.0110 | 1.375 | 1.4 | 1.38
0111 | 1.0111 | 1.4375 | 1.4 | 1.44
1000 | 1.1000 | 1.5 | 1.5 | 1.50
1001 | 1.1001 | 1.5625 | 1.6 | 1.56
1010 | 1.1010 | 1.625 | 1.6 | 1.62
1011 | 1.1011 | 1.6875 | 1.7 | 1.69
1100 | 1.1100 | 1.75 | 1.8 | 1.75
1101 | 1.1101 | 1.8125 | 1.8 | 1.81
1110 | 1.1110 | 1.875 | 1.9 | 1.88
1111 | 1.1111 | 1.9375 | 1.9 | 1.94
你说这个数字有多少个小数位? 你可以说2,因为在两位十进制数字范围内的每个值都被覆盖,尽管不是唯一的; 或者你可以说3,它涵盖了所有的唯一值,但不提供三位十进制数字范围内所有值的覆盖范围。
为了说明起见,我们会说它有2个十进制数字:小数精度将是可以表示这些十进制数字的所有值的位数。
好吧,那么,如果我们将所有数字减半(所以我们使用yyy
= -1)会发生什么?
xxxx | 1.xxxx | value | 1dd | 2dd
--------+----------+-----------+-------+--------
0000 | 1.0000 | 0.5 | 0.5 | 0.50
0001 | 1.0001 | 0.53125 | 0.5 | 0.53
0010 | 1.0010 | 0.5625 | 0.6 | 0.56
0011 | 1.0011 | 0.59375 | 0.6 | 0.59
0100 | 1.0100 | 0.625 | 0.6 | 0.62
0101 | 1.0101 | 0.65625 | 0.7 | 0.66
0110 | 1.0110 | 0.6875 | 0.7 | 0.69
0111 | 1.0111 | 0.71875 | 0.7 | 0.72
1000 | 1.1000 | 0.75 | 0.8 | 0.75
1001 | 1.1001 | 0.78125 | 0.8 | 0.78
1010 | 1.1010 | 0.8125 | 0.8 | 0.81
1011 | 1.1011 | 0.84375 | 0.8 | 0.84
1100 | 1.1100 | 0.875 | 0.9 | 0.88
1101 | 1.1101 | 0.90625 | 0.9 | 0.91
1110 | 1.1110 | 0.9375 | 0.9 | 0.94
1111 | 1.1111 | 0.96875 | 1. | 0.97
按照与之前相同的标准,我们现在处理1个十进制数字。 所以你可以看到,取决于指数,你可以有更多或更少的十进制数字,因为二进制和十进制浮点数不会互相干净地映射 。
相同的参数适用于双精度浮点数(使用52位尾数),只有在这种情况下,您将得到15或16位十进制数,具体取决于指数。
所有现代计算机都使用二进制浮点运算。 这意味着我们有一个二进制尾数,其单精度通常为24位,双精度为53位,扩展精度为64位。 (扩展精度可用于x86处理器,但不适用于ARM或其他类型的处理器。)
24,53和64位mantissas意味着对于2k和2k + 1之间的浮点数,下一个更大的数字分别是2k-23,2k-52和2k-63。 这是决议。 每个浮点运算的舍入误差至多是其中的一半。
那么如何转换成十进制数? 这取决于。
取k =0,1≤x<2。分辨率分别为2-23,2-52和2-63,分别约为1.19×10-7,2.2×10-16和1.08×10-19。 这比小数7,16和19小一点。 然后取k = 3和
8≤x<16.两个浮点数之间的差异现在是8倍大。 对于8≤x <10,分别只有6以上,小于15以及18以上的小数点。 但是对于10≤x<16,你还会得到一位小数!
如果x仅比2k + 1少一点,并且只有一点多于10n,例如1000≤x<1024,则可以得到最高的小数位数。如果x高一点,则得到最小的小数位数大于2k且小于10n,例如1/1024≤x<1/1000。 相同的二进制精度可以产生小数精度,其变化高达1.3位或log10(2×10)。
当然,你可以阅读文章“每个计算机科学家应该知道的关于浮点运算的知识”。
使用其硬件协处理器(最初为8087)的80x86代码提供三种精度级别:32位,64位和80位。 那些非常严格遵循1985年的IEEE-754标准。最近的标准规定了128位格式。 浮点格式具有24,53,65和113个尾数位,它们对应于精度的7.22,15.95,19.57和34.02十进制数字。
公式是mantissa_bits / log_2 10,其中10的日志基数是3.321928095。
虽然任何特定实现的精度不会改变,但浮点值转换为十进制时可能会出现这种情况。 请注意,值0.1
没有精确的二进制表示。 这是一个重复的位模式(0.0001100110011001100110011001100 ...),就像我们习惯的小数点,0.3333333333333约为1/3。
许多语言通常不支持80位格式。 有些C编译器可能会提供long double
,它使用80位浮点数或128位浮点数。 唉,它也可能使用64位浮点数,具体取决于实现。
NPU具有80位寄存器,并使用完整的80位结果执行所有操作。 在NPU堆栈内计算的代码可以从这种额外的精度中受益。 不幸的是,糟糕的代码生成 - 或者写得不好的代码 - 可能会通过将中间计算存储在32位或64位变量中来截断或舍入中间计算。
链接地址: http://www.djcxy.com/p/78619.html