给定一个数字,测试它是否是 Ramanujan 数(在我们的课程中定义为两个立方体的两种不同方式的总和)。它必须在 n^(1/3) 时间内运行。
我的代码可以正常工作——有时。随着测试值接近 2^63 -1,我遇到了一些随机错误。
奇怪的是,在我更改计数器的起始值以修复不同的错误之前,我通过了该范围内的数字测试。谁能告诉我为什么会这样?
我设置了一个 for 循环来为 a^3 创建值。
然后我设置 b=(na^3)^(1/3) 的值。
然后我测试 b 看它是否是一个整数。如果是这样,请打破循环。
在此处插入了一个 if 测试以使代码正常工作,尽管我不知道为什么需要这样做,这就是这个问题的要点。这个 if 语句为 n=2^63 以上和以下的值设置了两个不同的 for 循环
n < 2^63 的第二个循环以 c=a+1 开始,所以我不重复。这与第一个相同。
n > 2^63 的第二个循环以 c=a 开始。
为什么这会有所作为?为什么相同的代码不适用于越来越大的数字?
抱歉,我的代码太幼稚了,我才刚开始,很多功能在我的课程中都是禁止使用的。(例如,我不能使用 floor() 并且也不允许为它编写自己的函数)。
public class Ramanujan {
public static boolean isRamanujan(long n) {
if (n <= 0) return false;
long a3 = 0;
long c3 = 0;
double b = 0;
double d = 0;
for (int a = 1; a < n; a++) {
a3 = (long) a * a * a;
if (a3 > n) break;
b = Math.cbrt(n - a3);
if (b == (int) b) break;
}
if (n > Math.pow(2, 62)) {
for (int c = (int) Math.cbrt(a3); c < n; c++) {
c3 = (long) c * c * c;
if (c3 > n) break;
d = Math.cbrt(n - c3);
if (d == (int) d) break;
}
}
else {
for (int c = (int) Math.cbrt(a3) + 1; c < n; c++) {
c3 = (long) c * c * c;
if (c3 > n) break;
d = Math.cbrt(n - c3);
if (d == (int) d) break;
}
}
if (a3 + (long) b * b * b == c3 + (long) d * d * d && b * b * b != c3)
return true;
return false;
}
public static void main(String[] args) {
long n = Long.parseLong(args[0]);
StdOut.println(isRamanujan(n));
}
}
关于我为什么需要区分较大和较小数字的任何见解?