【问题标题】:Pow function returning wrong resultPow 函数返回错误结果
【发布时间】:2018-05-04 13:09:44
【问题描述】:

当我使用pow() 函数时,有时结果会差一。例如,这段代码产生 124,但我知道 5³ 应该是 125。

#include<stdio.h>
#include<math.h>

int main(){
    int i = pow(5, 3);
    printf("%d", i);
}

为什么结果不对?

【问题讨论】:

  • stackoverflow.com/questions/588004/… 对 int 使用 float pow() 很难预测。
  • 在您的程序中实现pow 的一个版本以使用积分输入。这将防止使用浮点数学的问题。
  • 看起来是学习如何使用调试器的绝佳机会。
  • 如果程序是 C 语言,请不要标记 C++,因为它不相关。
  • @JesperJuhl:我怀疑调试器在这里会有很大帮助。他已经确定了问题的位置,而且它是一个标准库函数,其代码甚至可能不可用(即使它可能也无济于事)。

标签: c math pow calculation


【解决方案1】:

您的问题是您将整数变量与浮点数学混合在一起。我敢打赌,由于舍入问题,5^3 的结果类似于124.999999,当转换为整数变量时,将floored 转换为124

有3种方法可以解决这个问题:

  1. 更安全地混合浮点数学和整数

    int x=5,y=3,z;
    z=floor(pow(x,y)+0.5);
    // or
    z=round(pow(x,y));
    

    但是使用它总是存在舍入错误影响结果的可能风险,尤其是对于更高的指数。

  2. 仅计算浮动变量

    所以将int 替换为floatdouble。这比 #1 安全一点,但在某些情况下它仍然不可用(取决于任务)。并且可能需要偶尔floor,ceil,round 才能正确获得想要的结果。

  3. 仅使用整数数学

    这是最安全的方式(除非您超过int 限制)。 pow 可以相对容易地在整数数学上计算出来:

【讨论】:

  • (1) 对于 IEEE754 double,在 2 的 53 次方内是安全的,并且是一个优雅的修复。 (2) 是个坏主意,(3) 到目前为止最好,所以 +2/3。
  • @Bathsheba 是的,他们声明相同。但是在有些任务中,#1、#2 方法就足够了,甚至是首选方法,但这一切都取决于任务和目标的准确性
【解决方案2】:

pow(x, y) 最有可能实现为 exp(y * log(x)):现代 CPU 只需轻按几下手腕即可评估 explog

虽然对于许多科学应用来说已经足够了,但是当将结果截断为整数时,即使是微不足道的参数,结果也可能会被关闭。这就是这里发生的事情。

您最好的选择是为整数参数滚动您自己的pow 版本;即从一个好的图书馆中找到一个。作为起点,请参阅The most efficient way to implement an integer based power function pow(int, int)

【讨论】:

    【解决方案3】:

    使用浮点数据类型

    #include <stdio.h>
    #include <math.h>
    
    int main()
    {
        float x=2;
        float y=2;
        float p= pow(x,y);
        printf("%f",p);
        return 0;
    }
    

    【讨论】:

    • 首选double。请注意,在将变量发送到使用它们的函数之前,它们会自动转换为double
    【解决方案4】:

    你可以用这个函数代替pow

    long long int Pow(long long int base, unsigned int exp)
    {
        if (exp > 0)
            return base * Pow(base, exp-1);
        return 1;
    }
    

    【讨论】:

    • 最好使用循环实现而不是递归实现。
    • 希望堆栈能抵抗高exp
    • @RSahu:是的,这也是一种选择。还有其他选项,甚至更高效,在 O(log(exp)) 中运行,但我认为这个家伙的主要问题是正确性而不是性能。
    • SO 已经有一堆实现,用来计算 int^int
    • 可能是我一段时间以来见过的最糟糕的Pow 实现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-05
    • 1970-01-01
    相关资源
    最近更新 更多