较高范围的浮点数可以比较低范围更准确地乘以/除/加/减。
例如,567.56 / 345.54
会比.00097854 / .00021297
更精确吗?
答案 0 :(得分:4)
你的问题的答案是“不”。浮点数(通常为*)用标准化的尾数和指数表示。乘法和除法首先在标准化的尾数上运行,然后在指数上运行。
加法和减法当然是另一个故事。像你的例子一样的操作:
567.56 + 345.54 or .00097854 - .00021297
工作正常。但是具有不同数量级的操作如
567.56 + .00097854 or 345.54 - .00021297
可能会失去一些低阶精度。
答案 1 :(得分:1)
对于IEEE 754二进制浮点数(最常见),浮点值在指数范围的大部分时间内具有相同的位数。然而,存在有效位数实际上更少位的范围的一部分。并且由舍入引起的相对误差确实取决于有效数位于其范围内的位置。
IEEE 754浮点数用符号表示(+1或-1,编码为0或1),指数(对于双精度,-1022到1023,编码为指数加1023,所以1到2046)和有效数(对于双精度,通常从1到2的分数,用53位表示但用52位编码,因为第一位隐式为1)。
,例如,数字6.5用位0(符号+1),10000000001(指数2)和1010000000000000000000000000000000000000000000000000(二进制分数1.1010,十六进制1.a,十进制1.3125)编码。我们可以用十六进制浮点写为0x1.ap2(十六进制分数1.a乘以2得到小数2的幂)。以十六进制浮点写入使人类能够相当容易地看到浮点表示。
对于指数,编码值0和2047是特殊的。当编码为0时,指数与编码为1(-1022)时相同,但分数的隐含位为0而不是1.当编码为2047时,浮点对象表示无穷大(如果有效位数都是零)或NaN(否则)。
当编码指数为0且有效位数均为零时,该数字表示零(其中+0和-0由符号区分)。如果有效位不是全为零,则认为该数字是非规范化的。这是因为通过调整指数使大多数数字“归一化”,使得分数在1(包括)和2(不包括)之间。对于非规范化数,分数小于1;它以“0”而不是“1”开头。
当浮点运算的结果是非正规化数时,它实际上在有效数中具有较少的位。因此,当数字低于0x1p-1022(2 -1022 )时,有效精度会降低。
当数字在正常范围内时(不会下溢到非正规数而不会溢出到无穷大),那么不同指数的数字的有效数没有差异,所以:
但请注意,相对错误可能会发生变化。执行浮点运算时,必须将精确的数学结果四舍五入为可表示的值。这种舍入只能在有效数字表示的单位中发生。对于给定的指数,有效数字中的位具有固定值。因此有效数字中的最后一位表示某个值。该值是接近1的有效数的一部分,而不是接近2的有效数。
对于双精度结果,最小精度单位(ULP)是有效数中最大位的值的2 52 中的1分。当使用舍入到最近模式(最常见的默认值)时,最大误差最多只有一半,因为,如果一个方向上的可表示数字超过ULP的一半,则另一个方向上的数字会减少超过ULP的一半。并且通过适当的浮点运算返回更接近的数字。
因此,有效数接近1的结果中的最大相对误差略高于2 -53 ,但有效数接近2的结果中的最大相对误差略低于2 -54
答案 2 :(得分:1)
为了完整起见,我不得不反对并说出是,这可能会有所影响......
实际上,如果你执行56756.0 / 34554.0,那么你将获得最接近的可表示的Float到精确的数学结果,一个浮点舍入“错误”。
这是因为56756.0和34554.0可以完全表示浮点(单精度或双精度IEEE 754),并且因为根据IEEE 754标准,操作执行精确的舍入操作(在默认模式下最接近)。
如果你写了567.56 / 345.54,那么这两个数字都没有完全用基数2中的浮点表示,所以这个操作的结果是累计3个浮点舍入“错误”。
让我们比较Squeak Smalltalk的双精度(Float)结果,转换为精确算术(分子和分母处任意整数长度的分数):
((56756.0 / 34554.0) asFraction - (56756 / 34554)) asFloat.
-> -7.932275867322412e-17
到目前为止,如此好,误差幅度小于或等于半个ulp,正如IEEE 754所承诺的那样:
(56756 / 34554) asFloat ulp / 2
-> 1.1102230246251565e-16
累积舍入误差可能会导致更大的误差(但绝不会更小):
((567.56 / 345.54) asFraction - (56756 / 34554)) asFloat
-> -3.0136736359825544e-16
((0.00056756 / 0.00034554) asFraction - (56756 / 34554)) asFloat
-> 3.647664511768385e-16
上面的例子很难概括,我完全同意其他答案:一般来说, NO ,你应该只关心相对精确度。
...除非你想要实现一些对舍入错误有非常严格容忍度的函数......
答案 3 :(得分:0)
没有。从某种意义上说,无论你的数字的数量级(指数部分)是多少,都有相同数量的有效数字。