浮点数,它什么时候出现,它是如何工作的



据我所知,float可以精确表示14个数字。

假设我们有

a = 564214623154
b = 54252

乘以这个c=a*b,它应该是30609771735350808,但当编译它显示我3.0609771735351E+16根据我的理解它会失去一些精度但是当我用c除以a时c/a我得到564214623154确切的结果没有任何精度损失

另一个例子假设我们有

c = 30609771735350808 
d = 30609761111111111

e=c-d应该是10624239697,但是当编译时它显示的是10624239696,所以精度丢失了

那么只有当我减去或加上两个数字时才会失去精度吗?

我用php

使用乘法和除法也可能失去精度。PHP和JavaScript以IEEE-754格式存储数字,其中包含52位尾数和11位指数。

让我们试试这些:

In Real Math(由Ruby生成):

45345657434523 * 9347287748322342 / 74387422372 = 5697991604786167788

在PHP和JavaScript

45345657434523 * 9347287748322342 / 74387422372 = 5697991604786168000

所以乘法和除法也会失去精度

编辑:在重新审视OP的问题时,似乎这不是一个很好的答案,因为结果包含超过15个十进制数字的精度。如果问题的目的是要对一堆精度为15位或更少的数字进行乘法和除法,那么最终结果往往会保持很高的精度(前提是不溢出或下溢)。所以你可以把1.25E35 * 2.5E7乘起来,正好得到3.125e+42因为PHP和JavaScript本质上是把有效数字组相乘,然后把指数加起来。然而,如果你把这两个值相加,你会得到1.25E35 + 2.5E7 = 1.25E35。没错,你把2500万加到一个数字上,它不会变!这是因为,正如OP所说,你只能得到14或15个十进制数字的精度。试着用手把这两个值相加,写出120000000000000000000000000000000000 + 25000000。14-15位数字从左边开始计数,不能全部拾取。

底线是精度问题更可能出现在加法和减法中。

在第一种情况下,没有损失精度,PHP只是将较大的数字格式化为浮点数。(在内部,这个数字被保存为浮点数。)试着这样做,得到"精确"的输出:

$a = 564214623154;
$b = 54252;
$c = $a * $b;
printf("%u, %un", $c, $c/$a);

接下来,在c * d的情况下,您的两个数字单独已经超过了标准ieee 64位浮点数的容量(它是53位,而您至少需要55位),因此在存储这些数字时已经失去了精度。

在加减法过程中失去精度的问题被称为"抵消":你花费所有存储空间的所有最高有效位都被抵消了,最终你没有足够的精确位来填满整个数字。这就是生活。

想象你坐在月球上,你在英国伍斯特测量了你哥哥的胡子长度。比较这两种测量方法的缺点是需要存储非常大的精度。

最新更新