有一些很棒的文档描述了浮点数的本质,以及为什么必须在某些浮点运算中丢失精度。例如。,: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
我有兴趣了解哪些浮点运算在底层数字的精度方面是无损的。例如,
$x = 2.0/3.0; # this is an operation which will lose some precision
但这会失去精确度吗?
$x = 473.25 / 1000000;
还是这个?
$x = 0.3429 + 0.2939201;
可以使用哪些一般经验法则来确定何时会丢失精度以及何时保留精度?
答案 0 :(得分:4)
通常,大多数操作都会引入一些精度损失。例外是在浮点中可精确表示的值(尾数可表示为非重复二进制)。在应用算术时,两个操作数和结果都必须能够在没有精度损失的情况下表达。
您可以构造没有精度损失的任意示例,但与域相比,此类示例的数量较少。例如:
1.0f / 8.0f = 0.125f
换句话说,尾数必须表达为A/B
,其中B是2的幂,并且(正如@ysth所指出的)A
和B
都小于一些上限,由表示中可用于尾数的总位数决定。
答案 1 :(得分:3)
你的问题是一个很大的假设。
问题不在于某些操作是否无损,而是将浮点数存储在一起是否会毫无损失。例如,从您的示例中获取此数字:
$x = .3429;
sprintf "%.20f", $x;
输出:
0.34289999999999998000
因此,要回答您的问题,某些操作在特定情况下可能无损。但是,它取决于原始数字和结果,所以永远不要指望它。
有关详情,请参阅perlnumber
。
答案 2 :(得分:3)
我认为你不会找到任何有用的经验法则。一般来说,如果以下两种情况都属实,精度不会丢失:
在第二个示例中,473.25 / 1000000,每个操作数都有一个精确的浮点表示,但商不具有。 (分母中任何因子为5的有理数在基数2中都有重复扩展,因此在浮点上没有精确表示。)上述规则不是特别有用,因为你无法提前告诉结果是否会通过观察操作数来确切地说;你还需要知道结果。