Java 如何快速找到最大的素因子?
我使用此代码查找数字的最大素数因数Java 如何快速找到最大的素因子?,java,performance,Java,Performance,我使用此代码查找数字的最大素数因数600851475143: BigInteger tal = new BigInteger("600851475143"); BigInteger tempBiggest = new BigInteger("2"); BigInteger temp = new BigInteger("2"); boolean check = true; for (BigInteger I = new BigInteger("2"); I
600851475143
:
BigInteger tal = new BigInteger("600851475143");
BigInteger tempBiggest = new BigInteger("2");
BigInteger temp = new BigInteger("2");
boolean check = true;
for (BigInteger I = new BigInteger("2"); I.compareTo(tal) < 0; I = I.add(BigInteger.ONE)) {
if (tal.mod(I).equals(BigInteger.ZERO)) {
temp = I;
if (temp.mod(new BigInteger("2")).equals(BigInteger.ZERO)) {
check = false;
} else {
for (BigInteger t = new BigInteger("2"); t.compareTo(temp) < 0; t = t.add(BigInteger.ONE)) {
if (temp.mod(t).equals(BigInteger.ZERO)) {
check = false;
break;
}
}
if (check) {
tempBiggest = I;
}
check = true;
}
}
}
System.out.println(tempBiggest);
System.exit(0);
biginger tal=新的biginger(“600851475143”);
BigInteger tempMaxim=新的BigInteger(“2”);
BigInteger温度=新的BigInteger(“2”);
布尔检查=真;
对于(biginger I=newbiginger(“2”);I.compareTo(tal)<0;I=I.add(biginger.ONE)){
if(总模(I)等于(BigInteger.ZERO)){
温度=I;
if(temp.mod(新的BigInteger(“2”)).equals(BigInteger.ZERO)){
检查=错误;
}否则{
对于(biginger t=newbiginger(“2”);t.compareTo(temp)<0;t=t.add(biginger.ONE)){
if(温度模(t.)等于(BigInteger.ZERO)){
检查=错误;
打破
}
}
如果(检查){
temp=I;
}
检查=正确;
}
}
}
System.out.println(最大值);
系统出口(0);
该代码适用于较小的数字,但不适用于较大的数字。有没有办法简化这个过程,或者我的整个代码都是错误构建的?首先,只循环到
sqrt(number)
其次,您可以跳过偶数,因此只需检查mod(2)
,然后检查mod(3)
,mod(5)
等
第三,在运行期间,您可以构建成功测试的素数列表,然后仅对该列表中的项目选中mod()
。这将节省大量时间,您可能会忘记第二点
最后,但并非最不重要-
检查
变量非常混乱,而是将其移动到内部块中,始终初始化为true
,并忘记下一个周期的最后一次更新。首先,只循环到sqrt(number)
其次,您可以跳过偶数,因此只需检查mod(2)
,然后检查mod(3)
,mod(5)
等
第三,在运行期间,您可以构建成功测试的素数列表,然后仅对该列表中的项目选中mod()
。这将节省大量时间,您可能会忘记第二点
最后,但并非最不重要-
check
变量非常混乱,而是将其移动到内部块中,始终初始化为true
,并忘记下一个周期的上次更新。这花费了我的平均计算机不到700毫秒:
public static void main(String[] args) {
long tal = 600851475143L;
int i;
for (i = 2; i <= tal; i++) {
if (tal % i == 0) {
tal /= i; i--;
}
}
System.out.println("largest prime factor is " + i); // largest prime factor is 6857
}
publicstaticvoidmain(字符串[]args){
长tal=600851475143L;
int i;
对于(i=2;i这花费了我的平均计算机不到700毫秒:
public static void main(String[] args) {
long tal = 600851475143L;
int i;
for (i = 2; i <= tal; i++) {
if (tal % i == 0) {
tal /= i; i--;
}
}
System.out.println("largest prime factor is " + i); // largest prime factor is 6857
}
publicstaticvoidmain(字符串[]args){
长tal=600851475143L;
int i;
对于(i=2;i最大的素数因子可以是最大的sqrt(num)。因此最好从这一点开始,然后向下,而不是向上。这样,一旦你有了因子,你就完成了
BigInteger sqrt = getApproxSquareRoot(num);
for (BigInteger t = sqrt; t.compareTo(2) > 0; t = t.add(BigInteger.ONE)) {
// if t divides num then you found it.
}
最大的素数因子可以是最大的sqrt(num)。因此最好从这开始,然后向下,而不是向上。这样,一旦你有了一个因子,你就完成了
BigInteger sqrt = getApproxSquareRoot(num);
for (BigInteger t = sqrt; t.compareTo(2) > 0; t = t.add(BigInteger.ONE)) {
// if t divides num then you found it.
}
您的代码是正确的,但您可以更改某些内容以使其快速运行。
例如,在第一个循环中,只向i
添加一个是没有用的,因为您将每两个步骤视为2的倍数。此外,您可以检查i.compareTo(sqrt(tal))<0;
,以避免其他无用的循环。
此外,我会考虑一种不使用检查的方法,您的代码是正确的,但您可以更改一些内容以使其快速运行。
例如,在第一个循环中,只向i
添加一个是没有用的,因为您将每两个步骤视为2的倍数。此外,您可以检查i.compareTo(sqrt(tal))<0;
,以避免其他无用的循环。
此外,我会考虑一种不使用检查的方法,这不适合长的吗?为什么要检查所有可能的因子,包括偶数?为什么不停在平方根?不管怎样,正如你所料,整数因子分解是计算中研究最为深入的领域之一。有很多答案可以回答这个问题他已经提出了具体问题。另请参见“快速”是一个相对术语。对于“较小”的数字,你可以在指数时间内完成,只需几秒钟。对于较大的数字,你就完蛋了(即(2^74207281-1)*(2^57885161-1))。如果您提出了多项式时间算法来计算任何整数的因子,请发布它并收集数百万。否则,计算大数将需要很长时间。请参阅。这不适合long
?为什么要检查所有可能的因子,包括偶数?为什么不在平方根处停止?无论如何,正如您所期望的,整数因子“快速”是一个相对术语。对于“较小”的数字,你可以在指数时间内完成,只需几秒钟。对于较大的数字,你就完蛋了(即(2^74207281-1)*(2^57885161-1))。如果您提出了多项式时间算法来计算任何整数的因子,请发布它并收集数百万。否则,对于大数来说,需要很长时间。请参阅。这是迄今为止最好的答案,因为它将目标数正确地除以发现的每个素因子,从而大大减少了所需的工作量。您应该定义y循环只到sqrt(数字)。这个具体数字并不重要,因为你很幸运,但对于像60085147514371这样的数字,你可以将其加速25000次。甚至跳过偶数50000次。@AntonínLejsek我恐怕循环到sqrt(60085147514371)
将导致错误答案,因为最大的素因子为882450139,大于sqrt(60085147514371)=77514