我正在尝试解决一些在线难题,找到一个非常大的数字的最大素数因子(准确地说是7393913335919140050521110339491123405991919445111971).在我寻找解决方案时,我偶然发现了这个Perl代码(
from here):
use strict;
use warnings;
my $magic = ;
sub largestprimef($);
sub max($$);
print largestprimef($magic);
sub largestprimef($) {
my $n = shift;
my $i;
return largestprimef(max(2, $n/2)) if($n % 2 == 0);
my $sn = int( sqrt($n) );
for ( $i = 3 ; $i <= $sn ; $i += 2 ) {
if ( $n % $i == 0 ) { last; }
}
if ( $i > $sn ) #loop ran over, means the number is prime
{
return $n;
}
else {
return max( $i, largestprimef( $n / $i ) );
}
}
sub max($$) {
return ( sort { $a <=> $b } (@_) )[1];
}
现在该算法似乎有效! Perl的一个小问题是它不接受真正的大数字.所以我改写了
my $magic = ;
至
my $magic = Math::BigInt->new(' ');
但这只是运行了很多年龄.所以我把它重写为Java(我更熟悉),这导致了这个:
static final BigInteger two = new BigInteger( "2" );
public static void main( String[] args ) {
BigInteger number = new BigInteger( "" );
System.out.println( goAtIt( number ) );
}
static BigInteger goAtIt( BigInteger prime ) {
if ( isEven( prime ) )
return goAtIt( prime.divide( two ).max( two ) );
BigInteger sqrt = sqrt( prime );
BigInteger comp = new BigInteger( "3" );
while (sqrt.compareTo( comp ) > 0) {
if ( prime.remainder( comp ).equals( BigInteger.ZERO ) )
break;
comp = comp.add( two );
}
if ( comp.compareTo( sqrt ) > 0 )
return prime;
return comp.max( goAtIt( prime.divide( comp ) ) );
}
作为辅助设备(看起来很好):
static boolean isEven( BigInteger number ) {
return number.getLowestSetBit() != 0;
}
static BigInteger sqrt( BigInteger n ) {
BigInteger a = BigInteger.ONE;
BigInteger b = new BigInteger( n.shiftRight( 5 ).add( new BigInteger( "8" ) ).toString() );
while (b.compareTo( a ) >= 0) {
BigInteger mid = new BigInteger( a.add( b ).shiftRight( 1 ).toString() );
if ( mid.multiply( mid ).compareTo( n ) > 0 )
b = mid.subtract( BigInteger.ONE );
else
a = mid.add( BigInteger.ONE );
}
return a.subtract( BigInteger.ONE );
}
但是我的结果总是关闭……而且我的Perl对原始代码进行逆向工程并不是那么好.有没有人知道我错过了什么?
==更新:问题(某种程度上)通过解决方法解决