将长数扩展到主要因素

时间:2015-10-19 22:15:27

标签: java types long-integer

我想把大数字分散到素数因素中。要做到这一点,我使用我的版本的Eratosthenes筛选(基本上我保持数组中范围内每个数字的最小素数因子)

        protected final static int PowOf2= 21;
        protected final static int[] Sieve = new int[(int) Math.pow(2,PowOf2)];
        protected final static int range = (int) Math.pow(2,PowOf2); //range of long types
        static int a=0; //counter


        public static void init(long n){
            for(int i=0; i<range-1; i++){
                Sieve[i]=i; //at first every number is equal to it's index
            }
            for(int i = 2; i*i <= range-1; i++) 
            {
                if (Sieve[i] == i){
                    for (int j = 2 * i ; j <= range-1; j += i)
                    {
                        Sieve[j] = i; //after that every number(index) has a smallest prime factor assigned to it 
                    }
                }

            }
        }

然后我使用这个数组将给定数字除以素因子

    public static long[] intoPrimeFactors (long n){
        long[] array = new long[range-1];

        while(!isPrime(n)){
            array[a]=Sieve[(int)n];  //here's an error
            n/=Sieve[(int) n];
            a++;
        }
        array[a]=n;

        return array;


    }

总的来说,我已经完成了所有因素

    public static void main(String[] args){
        long n=new Long(args[0]);
        init(Math.abs(n));
        long[] array = intoPrimeFactors(Math.abs(n)); //here's an error
        System.out.print(n+" = ");

        if(n<0){
            n=Math.abs(n);
            System.out.print("-1*");
        }

        for(int i=0;i<=a;i++){
            if(i!=a)System.out.print(array[i]+"*");
            else System.out.print(array[i]);
        }

    }

它在小数字(int)上运行得很好但是当我输入类似9223371331的东西时,我得到ArrayOutOfBound错误(在函数main和intoPrimeFactors中)并且我不确定为什么。你能帮帮我吗?

1 个答案:

答案 0 :(得分:1)

这是您初始化Sieve的方式:

protected final static int[] Sieve = new int[(int) Math.pow(2,PowOf2)];

其大小为:2097152

然后在intoPrimeFactors, 此代码将根据您输入的数字执行:

while(!isPrime(n)){
    array[a]=Sieve[(int)n];  //here's an error
    n/=Sieve[(int) n];
    a++;
}

如果有足够大的非素数输入,则会尝试超出Sieve的容量进行访问,从而产生ArrayOutOfBound。异常中的错误消息还会告诉您Sieve的确切索引。

那你能做什么?首先,有些事你不能做,这就是:

Sieve[(int) n]

如果n太大,则值会溢出,您将获得与您想要的索引不同的索引,索引错误。我猜你做了这个演员来修复编译器错误,但它没有意义。使用long变量作为数组索引,只有在int范围内,才能将int转换为int。在这种情况下,索引变量应该声明为long,而不是long。但这不是你的情况,因为你想支持非常大的数字。

但即使您可以使用TOKEN_QUERY作为数组索引,您的计算机是否有足够的内存来包含如此大的数组?我不信。如果要使用如此大的筛子,则需要创建自定义数据类型:

  • 它允许长索引
  • 当数据不适合内存时,它会将数据存储在其他地方(可能在磁盘上)

或者您可以在不使用筛子的情况下计算主要因子。请参阅此其他答案,例如:https://stackoverflow.com/a/12252237/641955