我正在搜索a、b和c,使得a^5+b^5 = c^5。我的程序生成2000^5+1= 2000^5。为什么会发生这种情况,以及如何修复?
public class Euler {
public static void main(String[] args) {
long i=0;
int power = 5;
int a1 = 1;
int a2 = 2000;
boolean isSolved = false;
long sumOfPowers = 0;
double root = 0;
long roundDown = 0;
long roundDown2Power = 0;
sumOfPowers = (long) (Math.pow(a1, power) + Math.pow(a2, power));
root = Math.pow(sumOfPowers, 1.0/power);
roundDown = (long) root;
roundDown2Power = (long)Math.pow(roundDown, power);
if (sumOfPowers == roundDown2Power) {
isSolved = true;
System.out.println(isSolved + " " + a1 + "^" + power + " + " + a2 + "^" + power + " + " + "^" + power + " = " + roundDown + "^" + power );
}
}
}我在寻找欧拉猜想的反例。我成功地使用了这个方法An error searching for a counterexample to Euler's conjecture 27^5 + 84^5 + 110^5 + 133^5 = 144^5 (着陆器和帕金,1966年),它需要6秒。我试图得到5800^4 + 217519^4 + 414560^4 = 422481^4 (Roger,1988年),但是在测试这个模块时,我发现我的程序生成2000^5+1=2000^5,这是一个问题。
发布于 2016-06-26 17:40:22
您应该尝试在Java中使用BigInteger库。
发布于 2016-06-26 18:46:34
你的问题是,长和双两种类型所能做的事情(并被精确地定义为要做的)和你对方程的纯数学观点的不匹配。
基元类型的值范围有限,可以表示。这就是你计算的绊脚石。long可以表示范围Long.MAX_VALUE (2^63-1)和Long.MIN_VALUE -(2^63)中的值。双类型可以代表一个更大的范围,但代价是准确性。表示为双数的整数只能精确地表示最多2^52,在最不重要(二进制)数字被删除的上方。这是因为这些类型的内存中有固定大小的64位,并且不可能在这些位中表示超过2^64个状态。
您的问题的解决方案不是使用这些类型,而是一个任意的精确类型,它可以精确地表示大数,而不需要截断或舍入。有用于此目的的BigInteger和BigDecimal类。请注意,BigDecimal仍然是圆的(例如,您不能用它表示1/3 ),只有您可以选择在哪里循环。
这些也是对象类型,这意味着您不能编写等式,您必须调用它们的方法来执行它们的操作。现有的行动也有些有限,需要重新安排一些问题来解决。
编辑:对于long和double类型的行为,没有任何特定的java,在任何为您提供相同类型的语言中都会遇到完全相同的问题。Double行为是一个指定的标准(IEEE-754),longs属性由双补规则(其大小为64位)决定。
https://stackoverflow.com/questions/38041297
复制相似问题