Java BigInteger 内存优化

发布于 2024-12-08 08:36:17 字数 953 浏览 1 评论 0原文

我正在尝试找到给定 N 个数字的 LCM。但我的这段代码占用了超过 32Mb 的内存。我可以在这里执行什么样的优化?

import java.util.Scanner ;
import java.math.BigInteger ; 
class Main {    
    public static BigInteger LCM( BigInteger a , BigInteger b ) {
        BigInteger c = a.gcd( b ) ;
        return a.multiply( b.divide( c ) ) ; 
    }
    public static void main( String[] args ) {
        Scanner s = new Scanner( System.in ) ;
        int n , t , ind , i ;    
        t = s.nextInt() ;
        for( ind = 1 ; ind <= t ; ind++ ) {
            n = s.nextInt() ;
            BigInteger res = BigInteger.ONE ;
            for( i = 0 ; i < n ; i++ ) {
                BigInteger a = s.nextBigInteger() ;
                res = LCM( res , a ) ;
            }
            System.out.println( "Case " + ind + ": " + res ) ;
        }
    }
}

示例输入:

2
3
2 20 10
4
5 6 30 60

示例输出:

Case 1: 20
Case 2: 60

I'm trying to find LCM of given N numbers. But this code of mine takes more than 32Mb memory. What kind of optimization can I perform here?

import java.util.Scanner ;
import java.math.BigInteger ; 
class Main {    
    public static BigInteger LCM( BigInteger a , BigInteger b ) {
        BigInteger c = a.gcd( b ) ;
        return a.multiply( b.divide( c ) ) ; 
    }
    public static void main( String[] args ) {
        Scanner s = new Scanner( System.in ) ;
        int n , t , ind , i ;    
        t = s.nextInt() ;
        for( ind = 1 ; ind <= t ; ind++ ) {
            n = s.nextInt() ;
            BigInteger res = BigInteger.ONE ;
            for( i = 0 ; i < n ; i++ ) {
                BigInteger a = s.nextBigInteger() ;
                res = LCM( res , a ) ;
            }
            System.out.println( "Case " + ind + ": " + res ) ;
        }
    }
}

Sample Input :

2
3
2 20 10
4
5 6 30 60

Sample Output :

Case 1: 20
Case 2: 60

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

女皇必胜 2024-12-15 08:36:17

也许你应该尝试一个好的任意精度数学库,比如 apfloat: http://www.apfloat.org/apfloat_java/< /a>
另一种方法是实现空间复杂度较低的算法。 :)

将它们全部因式分解,并将所有质因数与最大指数相乘。如果所有数字都小于 10000,则可以使用基元,然后使用 BigInt 进行乘法。这意味着要创建的对象要少得多。

Maybe you should try a good arbitrary precision math library like apfloat: http://www.apfloat.org/apfloat_java/
Another way is to implement an algorithm with lower space complexity. :)

Factorise all of them and multiply all prime factors with the greatest exponent. If all numbers are less than 10000, you can use primitives, and then do the multiplication with BigInt. This means far less objects to be created.

纵山崖 2024-12-15 08:36:17

该程序不占用 32MB 的任何内容。 JVM 的所有类加在一起及其关联的堆存储可能为 32MB。或者,加上 JVM 进程的开销,您的操作系统可能会报告它正在使用 32MB。

最接近的答案是:您不会通过更改程序来减少内存开销。

如果你的内存不足,那么就给它更多的内存。 java -Xmx1g 让堆变得非常大,如果需要的话可以达到 1GB。

This program is not taking 32MB of anything. All of the classes of the JVM put together and their associated heap storage might be 32MB. Or, adding on the overhead of the JVM process, your OS might report it's using 32MB.

The most proximate answer is: you're not going to reduce this memory overhead by changing your program.

If you're running out of memory, well, give it more memory. java -Xmx1g lets the heap grow very large, to 1GB if it wants.

挽心 2024-12-15 08:36:17

使用 BigInteger.ONE,而不是 new BigInteger("1"),但 32Mb 实际上并不算多,几乎任何 Java 代码都会占用它。

Use BigInteger.ONE, not new BigInteger("1"), but 32Mb isn't much really, practically any Java code takes that.

故笙诉离歌 2024-12-15 08:36:17

您可以使用 java 垃圾收集器来获得接受。只需在打印每种情况的解决方案后调用 System.gc() 即可。这是修改后的代码 -

import java.util.Scanner ;
import java.math.BigInteger ; 
class Main {    
    public static BigInteger LCM( BigInteger a , BigInteger b ) {
        BigInteger c = a.gcd( b ) ;
        return a.multiply( b.divide( c ) ) ; 
    }
    public static void main( String[] args ) {
        Scanner s = new Scanner( System.in ) ;
        int n , t , ind , i ;    
        t = s.nextInt() ;
        for( ind = 1 ; ind <= t ; ind++ ) {
            n = s.nextInt() ;
            BigInteger res = BigInteger.ONE ;
            for( i = 0 ; i < n ; i++ ) {
                BigInteger a = s.nextBigInteger() ;
                res = LCM( res , a ) ;
            }
            System.out.println( "Case " + ind + ": " + res ) ;
            System.gc();
        }
    }
}

You can use java garbage collector to get accepted. Just call System.gc() after printing the solution for each case. Here is the modified code -

import java.util.Scanner ;
import java.math.BigInteger ; 
class Main {    
    public static BigInteger LCM( BigInteger a , BigInteger b ) {
        BigInteger c = a.gcd( b ) ;
        return a.multiply( b.divide( c ) ) ; 
    }
    public static void main( String[] args ) {
        Scanner s = new Scanner( System.in ) ;
        int n , t , ind , i ;    
        t = s.nextInt() ;
        for( ind = 1 ; ind <= t ; ind++ ) {
            n = s.nextInt() ;
            BigInteger res = BigInteger.ONE ;
            for( i = 0 ; i < n ; i++ ) {
                BigInteger a = s.nextBigInteger() ;
                res = LCM( res , a ) ;
            }
            System.out.println( "Case " + ind + ": " + res ) ;
            System.gc();
        }
    }
}
未蓝澄海的烟 2024-12-15 08:36:17

如果您必须经常这样做,那么重新考虑该方法可能是个好主意。

您也许能够静态地为数字 1 到 10000 的因子创建一个数据结构,并遍历它以快速计算所有数字的 LCM。

这是一个猜测,但我认为你的内存使用率和速度都应该提高。

If you have to do this often then it might be a good idea to rethink the approach.

You might be able to statically create a data structure for factors of numbers 1 to 10000 and traverse it to quickly compute LCM of all numbers.

Its a guess but I think both your memory usage and speed should improve.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文