为什么pow(3 ^ 47)给出了错误的答案?

时间:2013-08-06 09:32:43

标签: php

使用php,此代码echo sprintf('%.9F',pow(3,47));输出26588814358957501972480.000000000

其他网站(如this)提供3^47 = 26588814358957503287787。 PHP有任何错误吗?如何解决?

顺便说一句,我想知道php使用pow,sprintf,fmod计算的最大数字是多少。是300位吗?

2 个答案:

答案 0 :(得分:2)

您需要使用外部程序或PHP扩展程序(库)。

我刚刚使用BC Math / GMP函数使用bcpow()gmp_pow()对其进行了测试,效果非常好:

<?php

// both output 26588814358957503287787
echo bcpow('3', '47');

echo gmp_strval( gmp_pow('3', '47') );

PHP.net文档有一个关于该主题的很好的部分:

  

浮点精度

     

浮点数的精度有限。虽然这取决于   在系统中,PHP通常使用IEEE 754双精度格式,   由于订单的舍入,这将产生最大的相对误差   1.11e-16。非基本算术运算可能会更大   错误,当然,必须考虑错误传播   几个操作复杂化。

     

此外,有理数的数字可以完全表示为   基数为10的浮点数,如 0.1 0.7 ,没有   精确表示为基数2中的浮点数,即   内部使用,无论尾数的大小。因此,他们   没有a就无法转换成它们的内部二进制对应物   精度损失小。这可能导致令人困惑的结果:for   例如, floor((0.1 + 0.7)* 10)通常会返回 7 而不是   预期 8 ,因为内部表示将是类似的   的 7.9999999999999991118 ...

     

所以永远不要将浮动数字结果信任到最后一位数,而不是   直接比较浮点数是否相等。如果更高   arbitrary precision math functionsgmp需要精确度   功能可用。

     

有关“简单”的解释,请参阅» floating point guide   标题为“我的数字为什么不加起来?”   
   - http://php.net/manual/en/language.types.float.php

请注意,php.ini configuration value 'precision'也可以在从浮点数转换为字符串时修改精度。

答案 1 :(得分:1)

在这种情况下,可以使用

bcpow()BCMath Arbitrary Precision Mathematics库的函数)。

echo bcpow('3', '47'); //as mentioned in ComFreek's answer
//outputs 26588814358957503287787 

pow无效的原因是pow()使用floatfloat的大小限制。

请参阅PHP Manual

中的摘录
  

浮点数的大小取决于平台,但最大值为〜1.8e308,精度约为14位十进制数是一个常见值(64位IEEE格式)

换句话说,最大可能的大小可能会有所不同 - 即(对于32位和64位系统可能不同)。

希望能回答你的问题!