代码之家  ›  专栏  ›  技术社区  ›  user1537366

对于某些正整数n,m,(int)pow(n,m)会错吗?

  •  5
  • user1537366  · 技术社区  · 9 年前

    假设 n m 为正整数,n 在整数范围内,将 (int)pow(n,m) 曾经给出过错误的答案吗?

    我试过很多 n 对于 m=2 到目前为止没有得到任何错误的答案。

    4 回复  |  直到 9 年前
        1
  •  8
  •   Community CDub    7 年前

    C标准对浮点运算的精度没有任何要求。准确度为 定义的实现 这意味着需要实现来记录它。然而,实施过程中留下了一个重要的“出局”:(§5.2.4.2.2第6段,增加了重点。)

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

    事实上,gcc通过指定 the accuracy is unknown 尽管如此,即使不能保证,glibc计算的准确性也相当好。

    已知MS libc实现偶尔会为 pow 函数,如果 功率,功率 操作被简单地截断为 int 。(我在Visual Studio文档中找不到关于浮点精度的任何规范,但我相信下面的SO问题列表为我的断言提供了证据。)

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

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

    SO实际上充满了由这个特定问题引起的问题。参见:

    毫无疑问还有更多。

        2
  •  3
  •   Brett Hale    9 年前

    一些实现评估 pow(x,y) exp(y*log(x)) 在任何情况下,其他人对整数指数使用平方乘幂。

    glibc 例如,具有“C” implementations ,以及具有查找表、多项式近似等的平台特定实现。许多Sun/BSD衍生物似乎将整数指数作为一种特殊情况来处理。

    更重要的是,IEEE-754不需要它。它也没有规定结果所需的准确性。油嘴滑舌的 documents 它的最大ulp错误,尽管此页面可能不是最新的。

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

        3
  •  0
  •   fuz    9 年前

    在平台上 int 具有64位和 double 也有64位,这可能无法作为 双重的 (的论点和结果 pow() )没有足够的尾数来精确表示每个64位整数。在普通平台上 整数 具有32位和 双重的 是64位IEEE754浮点型,您的假设是正确的。

        4
  •  0
  •   Art    9 年前

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

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

    IEEE 754二进制64浮点数(这是大多数现代机器上常用的双精度表示)可以精确表示所有整数[0,2^53]。