我在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
工作正常,但我第一次尝试的方式不同:
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
的结果却是。{/ p>
任何人都能告诉我是什么原因导致模运算符仍然在这里给1.09
余数?
答案 0 :(得分:7)
任何人都能告诉我是什么原因导致模运算符仍然在这里给出1.09余数?
正常的浮点不准确,基本上。您使用的值不是完全日志(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
。
答案 1 :(得分:2)
Math.log(729) = 6.591673732008658
Math.log(3) = 1.0986122886681098
d= 1.0986122886681093
如果您注意到,d (1.0986122886681093)
稍微小于(最后一位数字)而不是Math.log(3)-(1.0986122886681098)
值,那么它似乎工作正常。您可能缺少双数据类型精度理解。 浮点数对于高精度值有一些不准确性,因为它们的实际表示。