Duże liczby w Javie

95

Jak bym się zabrał do wykonywania obliczeń na bardzo dużych liczbach w Javie?

Próbowałem, longale to osiąga maksimum na 9223372036854775807, a przy użyciu liczby całkowitej nie zapisuje wystarczającej liczby cyfr i dlatego nie jest wystarczająco dokładny dla tego, czego potrzebuję.

Czy jest w tym jakiś sposób?

Petey B.
źródło
3
9223372036854775807to dokładna wartość Long.MAX_VALUE.
Jin Kwon

Odpowiedzi:

154

Możesz użyć tej BigIntegerklasy dla liczb całkowitych i BigDecimaldla liczb z cyframi dziesiętnymi. Obie klasy są zdefiniowane w java.mathpakiecie.

Przykład:

BigInteger reallyBig = new BigInteger("1234567890123456890");
BigInteger notSoBig = new BigInteger("2743561234");
reallyBig = reallyBig.add(notSoBig);
Fabio Vinicius Binder
źródło
8
Warto wspomnieć o (choć wydaje mi się, że dla większości oczywistych) spadkiem wydajności wynikającym z użycia klasy BigInteger, jeśli planujesz wykonywać z tym obliczenia.
haylem
@haylem szybkość działania jest taka sama, ale długość numeru sprawia, że ​​wymaga to czasu. używają operatorów bitowych do wykonywania obliczeń. jak to, co dzieje się normalnie podczas wykonywania matematyki na typach prymitywnych.
Eboubaker
18

Oto przykład, który bardzo szybko daje duże liczby.

import java.math.BigInteger;

/*
250000th fib # is: 36356117010939561826426 .... 10243516470957309231046875
Time to compute: 3.5 seconds.
1000000th fib # is: 1953282128707757731632 .... 93411568996526838242546875
Time to compute: 58.1 seconds.
*/
public class Main {
    public static void main(String... args) {
        int place = args.length > 0 ? Integer.parseInt(args[0]) : 250 * 1000;
        long start = System.nanoTime();
        BigInteger fibNumber = fib(place);
        long time = System.nanoTime() - start;

        System.out.println(place + "th fib # is: " + fibNumber);
        System.out.printf("Time to compute: %5.1f seconds.%n", time / 1.0e9);
    }

    private static BigInteger fib(int place) {
        BigInteger a = new BigInteger("0");
        BigInteger b = new BigInteger("1");
        while (place-- > 1) {
            BigInteger t = b;
            b = a.add(b);
            a = t;
        }
        return b;
    }
}
Peter Lawrey
źródło
1
W przypadku naprawdę dużych liczb Fibonacciego rekurencyjne obliczenia są absurdalnie czasochłonne. O wiele lepiej jest użyć wyraźnej formuły Bineta . Kilka Math.pow () si Math.sqrt () później, gotowe! :)
Zubin Mukerjee
2
@ZubinMukerjee jednak pow i sqrt na BigDecimal też nie są tanie. Jest lepsze niż iteracja, ale nie jest tak proste, jak się wydaje.
Peter Lawrey
13

Do kasy BigDecimali BigInteger.

Clint Miller
źródło
6
import java.math.BigInteger;
import java.util.*;
class A
{
    public static void main(String args[])
    {
        Scanner in=new Scanner(System.in);
        System.out.print("Enter The First Number= ");
        String a=in.next();
        System.out.print("Enter The Second Number= ");
        String b=in.next();

        BigInteger obj=new BigInteger(a);
        BigInteger obj1=new BigInteger(b);
        System.out.println("Sum="+obj.add(obj1));
    }
}
Rupendra Sharma
źródło
3

W zależności od tego, co robisz, możesz rzucić okiem na GMP (gmplib.org), która jest wydajną biblioteką o wielu precyzjach. Aby używać go w Javie, potrzebujesz opakowań JNI wokół biblioteki binarnej.

Zobacz część kodu Alioth Shootout, aby zobaczyć przykład użycia go zamiast BigInteger do obliczenia liczby Pi na dowolną liczbę cyfr.

https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/pidigits-java-2.html

Trevor Tippins
źródło