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

时间:2015-09-02 12:33:39

标签: c floating-accuracy

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

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

4 个答案:

答案 0 :(得分:8)

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

  

浮点运算(+-*/)以及<math.h>和{{中的库函数的准确性返回浮点结果的1}}是实现定义的,因为<complex.h><stdio.h>和{中的库函数执行的浮点内部表示和字符串表示之间的转换准确性也是如此{1}}。 实施可能会说明   准确性未知。

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

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

在x86架构上,大多数实现都尝试实现IEEE 754,因为本机浮点表示符合。但是,在2008年修订版之前,IEEE-754仅要求powpowint+-提供正确的结果。自修订以来,it recommends许多其他函数返回正确的舍入结果,但所有这些建议都是可选的,并且很少有数学库实现所有这些。

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

实际上,这个特定问题导致了很多问题。参见:

毫无疑问还有更多。

答案 1 :(得分:3)

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

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

更重要的是,IEEE-754并不需要它。它也没有规定结果所要求的准确性。 glibc documents其最大ulp错误,但此页面可能不是最新的。

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

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

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