7

我有下一个功能:

static bool isPowerOf(int num, int power)
{
        double b = 1.0 / power;
        double a = Math.Pow(num, b);
        Console.WriteLine(a);
        return a == (int)a;
}

我插入了打印功能进行分析。

如果我调用该函数:

isPowerOf(25, 2)

它返回真,因为5^2等于 25。但是,如果我调用 16807,也就是7^5,下一个方法:

isPowerOf(16807, 5)

在这种情况下,它会打印 '7' 但a == (int)a返回 false。

你能帮我吗?谢谢!

4

4 回答 4

6

尝试使用小 epsilon 来计算舍入误差:

return Math.Abs(a - (int)a) < 0.0001;

正如 harold 所建议的,如果a恰好比整数值略小,比如 3.99999,最好进行舍入:

return Math.Abs(a - Math.Round(a)) < 0.0001;
于 2012-07-06T09:43:59.740 回答
5

已经提出了解决问题的比较,但实际上这里的问题是根本不应该涉及浮点。您想要一个涉及整数的问题的准确答案,而不是对固有的不准确测量进行的计算的近似值。

那么这还能怎么做呢?

首先想到的是作弊:

double guess = Math.Pow(num, 1.0 / power);
return num == exponentiateBySquaring((int)guess, power) ||
       num == exponentiateBySquaring((int)Math.Ceil(guess), power);
       // do NOT replace exponentiateBySquaring with Math.Pow

只要guess小于 1 就可以工作。但我不能保证它总是适用于您的输入,因为并不总是满足这个条件。

So here's the next thing that comes to mind: a binary search (the variant where you search for the upper boundary first) for the base in exponentiateBySquaring(base, power) for which the result is closest to num. If and only if the closest answer is equal to num (and they are both integers, so this comparison is clean), then num is a power-th power. Unless there is overflow (there shouldn't be), that should always work.

于 2012-07-06T10:04:47.933 回答
2

如果您调试代码,然后您可以在第一次比较中看到:

isPowerOf(25, 2) 

a 持有5.0 Here 5.0 == 5 => 这就是为什么你得到 true

并在第二isPowerOf(16807, 5)

a 持有7.0000000000000009

并且因为7.0000000000000009 != 7=> 你是假的。和 Console.WriteLine(a) 正在截断/舍入双精度,仅显示 7

这就是为什么您需要像 Dani 的解决方案那样比较最接近的值

于 2012-07-06T09:49:37.617 回答
2

Math.Powdoubles 进行运算,因此在求根时会出现舍入误差。如果你想检查你是否找到了一个确切的力量:

  • 当前执行Math.Pow,以提取根
  • 将结果四舍五入到最接近的整数
  • 将此整数提高到提供的功率,并检查您是否获得了提供的目标。Math.Pow将精确int到整数幂时范围内的数字
于 2012-07-06T09:51:46.590 回答