据我所知,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
答案 0 :(得分:1)
也可能通过乘法和除法失去精度。 PHP和JavaScript以IEEE-754格式存储数字,具有52位尾数和11位指数。有些整数是完全代表的,有些则不是。
让我们试试这些:
在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位数字从左边开始计数,你不能全部拿起它们。
底线是加法和减法更容易出现精度问题。很高兴知道。
答案 1 :(得分:1)
在你的第一种情况下,你没有精确度,PHP只是将较大的数字格式化为浮点数。 (在内部,数字保持为浮点数。)试试这个得到“精确”输出:
$a = 564214623154;
$b = 54252;
$c = $a * $b;
printf("%u, %u\n", $c, $c/$a);
接下来,在c * d
的情况下,你的两个数字已经超过了标准IEEE-64位浮点数的容量(53位,而你需要至少55位),所以精度是当你存储这些数字时已经丢失了。
在加法/减法期间丢失精度的问题称为“取消”:您将所有存储空间全部取消的所有最重要的位都被取消,并且您最终没有足够的准确位来填充manitssa。 C'est la vie。
想象一下,你坐在月球上,在英国伍斯特(Worcester)对你兄弟的胡须长度进行两次测量。比较这两个测量值时,您需要存储非常大的精度。