对于某些正整数n,m,will(int)pow(n,m)是错误的吗?

假设nm是正整数,并且n m在整数范围内,那么(int)pow(n,m)给出错误的答案吗?

我为m=2尝试了很多n ,到目前为止还没有得到任何错误的答案。

C标准对浮点运算的精度没有任何要求。 准确性是实现定义的 ,这意味着需要实现来记录它。 然而,实现留下了重要的“结果”:(第5.2.4.2.2段第6段,重点增加。)

返回浮点结果的中的浮点运算( +-*/ )和库函数的准确性是实现定义的,精度也是由的库函数执行的浮点内部表示和字符串表示之间的转换。 实施可能表明准确性未知。

事实上,gcc通过指定准确性未知来利用这一点。 尽管如此,即使没有保证,glibc计算的准确性也相当不错。

已知MS libc实现偶尔会为具有整数参数的pow函数产生1ULP的错误,如果将pow操作的结果简单地截断为int则会导致错误的值。 (我在Visual Studio文档中找不到关于浮点精度的任何规范,但我相信下面的SO问题列表提供了我断言的证据。)

在x86体系结构中,大多数实现都尝试实现IEEE 754,因为本机浮点表示符合。 但是,在2008年修订版之前,IEEE-754只需要+-*/sqrt正确舍入结果。 自修订以来, 它建议许多其他函数返回正确的舍入结果,但所有这些建议都是可选的,并且很少有数学库实现所有这些。

如果你真的想用pow来计算整数的整数幂,那么建议(并且很容易)使用lround(pow(n, m))而不是(long)(pow(n, m)) ,这将绕过得到最接近的整数,而不是乐观地依赖于误差为正。 如果pow在1ULP之内,那么应该为结果提供正确的整数值,最多为2 52 (使用IEEE-754双倍)。 在2 52和2 53之间 ,1ULP误差为0.5,有时会舍入到错误的整数。 超过2 53并非所有整数都可以表示为双精度。

因此,这个问题实际上充满了问题。 看到:

  • 使用C中的POW函数反转五位数字
  • C的pow()函数根据头文件无法正常工作
  • powfunction的奇怪行为
  • 为什么在使用带有电源的地板时会出现意外的输出?
  • 为什么在C ++中pow(10,5)= 9,999
  • 如果赋值为整数,则将pow()的返回值向下舍入 (由LưuVĩnhPhúc找到)
  • 电源function错误输出 – C (也)

毫无疑问,还有更多。

一些实现在任何情况下都将pow(x,y)评估为exp(y*log(x)) ,而其他实现则使用平方乘法为积分指数。

例如, glibc具有’C’ 实现 ,以及具有查找表,多项式近似等的特定于平台的实现。许多Sun / BSD派生物似乎作为特殊情况处理整数指数。

更重要的是,IEEE-754不要求它。 它也没有规定结果所要求的准确性。 glibc 记录了它的最大ulp错误,尽管这个页面可能不是最新的。

总之,即使pow(n,m)具有精确的浮点表示, 也不要假设精确的积分结果

int有64位且double也有64位的平台上,这可能不能用作doublepow()的参数和结果没有足够的尾数来精确表示每个64位整数。 在一个普通的平台上, int有32位, double是64位IEEE 754浮点类型,你的假设是正确的。

这取决于整数和双精度的大小。

使用32位整数和64位IEEE 754 double,它将为所有可能的整数提供正确的答案。

IEEE 754 binary64浮点数(在大多数现代机器上通常表示双精度数)可以精确地表示所有整数[0,2 ^ 53]。