所以我现在正在研究一个java代码。我已经完全正常工作,但是任务的重点是使它分解大数(超过30位)。这样做,但它可能需要15分钟才能完成,这是不行的。我的教授向我保证,我使用的算法适用于最多2 ^ 70的数字,并且应该在大约五分钟内完成。我一直试图想出办法(增加2而不是1等),但我似乎无法弄清楚如何在不跳过某些因素的情况下让它更快地移动。有任何想法吗?我还认为Elliptic Curve方法会更好,但他告诉我现在不要处理它。
这是我的代码(ps,sqrt是我自己的函数,但我确信它正在运行):
public String factorizer(BigInteger monster){
System.out.println("monster =" + monster);
String factors = "";
BigInteger top = maths.monsterSqrt(monster);
if(monster.mod(two).equals(0));
BigInteger jump = two;
for(BigInteger bi = two; bi.compareTo(top) <= 0; bi = bi.add(jump)){
while(monster.mod(bi).equals(zero)){
factors += "+" + bi + "";
monster = monster.divide(bi);
jump = one;
}
}
if(monster.compareTo(BigInteger.ONE) == 1){
factors += "+" + monster;
}
return factors;
}
答案 0 :(得分:6)
这是我的试验部门的整数分解版本:
public static LinkedList tdFactors(BigInteger n)
{
BigInteger two = BigInteger.valueOf(2);
LinkedList fs = new LinkedList();
if (n.compareTo(two) < 0)
{
throw new IllegalArgumentException("must be greater than one");
}
while (n.mod(two).equals(BigInteger.ZERO))
{
fs.add(two);
n = n.divide(two);
}
if (n.compareTo(BigInteger.ONE) > 0)
{
BigInteger f = BigInteger.valueOf(3);
while (f.multiply(f).compareTo(n) <= 0)
{
if (n.mod(f).equals(BigInteger.ZERO))
{
fs.add(f);
n = n.divide(f);
}
else
{
f = f.add(two);
}
}
fs.add(n);
}
return fs;
}
我的博客上的essay解释了这段代码,其中也有Pollard的rho算法的解释,它可能更适合分解大整数。
顺便说一下,如今30位数字并不是一个特别大的因素分解问题。任何超过几秒的东西都太长了。
答案 1 :(得分:2)
当您将monster
除以素因子时,您还应相应地调整top
。实际上,外部循环将始终以1或2的增量运行到原始数字的平方根,对于30位数字,其大小为10 ^ 15步...这是想知道的你只用了15分钟就完成了!
如果你的怪物数量具有非常大的素数因子(比如它本身就是素数),那么在任何情况下你都可以忘记它的良好表现。
请注意,您的示例代码的增量错误:如果原始数字不均匀,那么jump
将始终保持two
,这意味着您只调查偶数因子,因此无法找到任何因素。< / p>
答案 2 :(得分:0)
不确定为什么要返回String!
这对我有用。请注意,它每次都会i
与n / i
和n = n / i
进行比较:
// Memoization of factors.
static Map<BigInteger, List<BigInteger>> factors = new HashMap<>();
private static final BigInteger TWO = BigInteger.ONE.add(BigInteger.ONE);
public static List<BigInteger> factors(BigInteger n, boolean duplicates) {
// Have we done this one before?
List<BigInteger> f = factors.get(n);
if (f == null) {
// Start empty.
f = new ArrayList<>();
// Check for duplicates.
BigInteger last = BigInteger.ZERO;
// Limit the range as far as possible.
for (BigInteger i = TWO; i.compareTo(n.divide(i)) <= 0; i = i.add(BigInteger.ONE)) {
// Can have multiple copies of the same factor.
while (n.mod(i).equals(BigInteger.ZERO)) {
if (duplicates || !i.equals(last)) {
f.add(i);
last = i;
}
// Remove that factor.
n = n.divide(i);
}
}
if (n.compareTo(BigInteger.ONE) > 0) {
// Could be a residue.
if (duplicates || n != last) {
f.add(n);
}
}
// Memoize.
factors.put(n, f);
}
return f;
}