我试图制定一种方法来对数字进行素数分解,它可能不是最有效的,但我不明白它为什么不能工作。
public static ArrayList<Integer> primeFactorize(int num) {
ArrayList<Integer> primeFactors = new ArrayList<Integer>();
for (int i = 2; i < Math.sqrt((double) num); i++) {
if (isPrime(i) && factor(num).contains(i)) {
primeFactors.add(i);
num /= i;
if (isPrime(num)) {
primeFactors.add(num);
break;
}
i = 2;
}
}
return primeFactors;
}
它调用了我写的另外两个名为factor()
和isPrime()
的方法,这些方法完全符合您的预期(返回ArrayList
因子和true
}或false
取决于输入是否分别为素数。
我通过调试器,num
为12,它在第一个循环中工作正常,在primeFactors
中添加了2。但是,当它在num
为6且i
为2时再次到达数组顶部时,它会退出循环,就好像i < Math.sqrt((double) num)
返回false
一样。
但这没有意义,因为6的平方根有点超过2.我也试过(double) i < Math.sqrt((double) num)
,但它只是做了同样的事情。
任何人都能看到我失踪的东西吗?感谢您的回复。
编辑:这是我的代码,感谢您的帮助!我知道我可以确保它更有效率,所以我可能会在以后这样做,但现在这是完美的。public static ArrayList<Integer> primeFactorize(int num) {
ArrayList<Integer> primeFactors = new ArrayList<Integer>();
int i = 2;
while (i < Math.sqrt((double) num)) {
if (isPrime(i) && num % i == 0) {
primeFactors.add(i);
num /= i;
if (isPrime(num)) {
primeFactors.add(num);
break;
}
i = 2;
}
else
i++;
}
return primeFactors;
}
答案 0 :(得分:4)
在for
循环中,i++
部分将在每个循环结束时被调用。所以在你的代码中,你将i
设置为2.然后,循环结束,并将{1}增加1,使其为3.然后进行比较,3超过sqrt(6 ),所以循环退出。
如果希望i
在下一次迭代中为2,则需要将其设置为一个值,以便在增量操作运行后将为2,而不是前;在这种情况下,您应该将其设置为1.更好的解决方案是更改您的代码结构,因此它不是必需的。 As pointed out by biziclop,i
循环可让您决定是否增加,并避免此问题。
答案 1 :(得分:3)
既然您已经接受了答案,我认为您的问题已经解决了。我想要指出的是,如果有另一种方式,将整数转换为双精度通常是一个坏主意。因此,我想向您展示以下实现,它不使用浮点运算。另外我认为检查num
是否为素数是一个坏主意,因为这会降低算法的速度。此外,如果num % i == 0
的计算结果为true,则i
始终为素数,因此isPrime(i)
检查是多余的,也会降低算法速度。
List <Integer> primeFactors(int n) {
List<Integer> factors = new ArrayList<>();
for (int i = 2; i <= n / i; ++i) {
while (n % i == 0) {
factors.add(i);
n /= i ;
}
}
if (n > 1) {
factors.add(n);
}
return factors ;
}