Mar*_*ans 4 java mathematical-optimization floating-accuracy modulo
我在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
Run Code Online (Sandbox Code Playgroud)
工作正常,但我第一次尝试的方式不同:
public boolean isPowerOf(int z, int n) {
double output = Math.log(n) % Math.log(z);
if(output != 0) {
return false;
} else {
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
然而,对于log(729) % log(3)似乎回归1.0986122886681093,而结果log(729) / log(3) is 6.
任何人都能告诉我是什么原因导致模数运算符仍然1.09在这里给出余数?
任何人都能告诉我是什么原因导致模运算符仍然在这里给出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);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
6.591673732008658
1.0986122886681098
1.0986122886681093
Run Code Online (Sandbox Code Playgroud)
换句话说,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);
Run Code Online (Sandbox Code Playgroud)
在数据变得"非常大"之前,你应该可以解决浮点不准确问题.BigInteger如果你想精确处理非常大的数字,你可以使用.