4

我在Java中有以下工作方法:

/**
 * Determines if n is a power of z
 * 
 * @param z the number that n may be a power of
 * @param n the number that may be a power of z
 * @return true if n is a power of z 
 */
public boolean isPowerOf(int z, int n) {
    double output = Math.log(n) / Math.log(z);
    if(output % 1 > 0) {
        return false;
    } else {
        return true;
    }
}

isPowerOf(3, 729); //returns true, because 3^6 = 729

工作正常n强大,但我第一次尝试不同:

public boolean isPowerOf(int z, int n) {
    double output = Math.log(n) % Math.log(z);
    if(output != 0) {
        return false;
    } else {
        return true;
    }
}

然而,对于log(729) % log(3)似乎回归1.0986122886681093,而结果log(729) / log(3) is 6

谁能告诉我是什么原因导致模运算符仍然1.09在这里给出余数?

4

2 回答 2

7

谁能告诉我是什么原因导致模运算符在这里仍然给出 1.09 余数?

基本上,正常的浮点数不准确。您使用的值不完全是log(729) 和 log(3)。如果您看一下log(3)log(729) % log(3)您会发现它们几乎完全相同:

public class Test {
    public static void main(String[] args) {
        double x = Math.log(729);
        double y = Math.log(3);
        System.out.println(x);
        System.out.println(y);
        System.out.println(x % y);
    }
}

输出:

6.591673732008658
1.0986122886681098
1.0986122886681093

换句话说,log(729)是有效的log(3) * 5.9999999999999(或类似的东西)。基本上,您可能希望为您的测试添加一些容差,并返回余数是否非常接近 0非常接近log(z).

或者,使用log和除法“粗略地”计算出功率应该是多少,然后Math.pow检查确切的值:

int power = (int) (Math.log(n) / Math.log(z) + 0.5);
return n == Math.pow(z, power);

在这里,在数字变得“相当大”之前,您在浮点不准确性方面应该没问题。如果您想精确BigInteger处理非常大的数字,您可以使用。

于 2012-10-23T13:47:46.360 回答
2
Math.log(729)  = 6.591673732008658
Math.log(3) = 1.0986122886681098

d= 1.0986122886681093

如果您注意到,它d (1.0986122886681093)比 value add 略小(最后一位), Math.log(3)-(1.0986122886681098)它似乎工作正常。可能您缺少对双精度数据类型的理解。由于浮点数的实际表示形式,浮点数对于高精度值有一些不准确之处。

于 2012-10-23T13:48:26.733 回答