2009-08-20 13 views
6

Obecnie uczę siebie Ada i chociaż mogę zacząć od rozwiązania niektórych bardziej konwencjonalnych problemów, aby zacząć.Arbitralna długość całkowita w Ada

Dokładniej staram się obliczyć silnię n !, natomiast n> 100. Moja implementacja tak daleko jest:

with Ada.Text_IO; 
with Ada.Integer_Text_IO; 

use Ada.Text_IO; 

procedure Factorial is 
    -- define a type covering the range beginning at 1 up to which faculty is to 
    -- be computed. 
    subtype Argument is Long_Long_Integer range 1..100; 

    -- define a type that is large enough to hold the result 
    subtype Result is Long_Long_Integer range 1..Long_Long_Integer'Last; 
    package Result_IO is new Ada.Text_IO.Integer_IO(Result); use Result_IO; 

    -- variable holding the faculty calculated. 
    fac : Result := 1; 

begin 
    -- loop over whole range of ARGUMENT and calculate n! 
    for n in ARGUMENT loop 
     fac := (fac * n); 
    end loop; 
end; 

Problemem jest to, oczywiście, że nawet Long_Long_Integer jest może zbyt mała dla tego i zgłasza wyjątek CONTRAINT_ERROR dla n> 20.

Czy istnieje pakiet implementujący liczby całkowite o dowolnej wielkości?

Dzięki!

PS: Oparłem się na rekursji, ponieważ chciałem zbadać pętle w tym ćwiczeniu. Ale w innych przypadkach prosimy o komentowanie wszystkich aspektów kodu (styl, najlepsze praktyki, błąd ..)

Odpowiedz

8

Biblioteka Ada Crypto obsługuje duże liczby bez znaku (Big_Numbers). Możesz pobrać lib z http://sourceforge.net/projects/libadacrypt-dev/. Polecam sprawdzenie svn. Funkcja mnożenia Big_Numbers obecnej wersji ma niewielki błąd.

Można skompilować bibliotekę z bieżącym kompilatorem GNAT z wersji the AdaCore Libre site.

Biblioteka nie będzie kompilowana pod kontrolą gcc-4.3 lub gcc-4.4 z powodu a bug in gcc.

Na koniec dam ci mały przykład, jak pomnożyć dwa 512-bitowe numery Big_Numbers z LibAdaCrypt.

package Test.Big_Numbers is 

with Crypto.Types.Big_Numbers; 

pragma Elaborate_All(Crypto.Types.Big_Numbers); 

package Big is new Crypto.Types.Big_Numbers(512); 
    use Big; 
    use Big.Utils; 
end Test.Big_Numbers; 



package body Test.Big_Numbers is 

x : Big_Unsigned := To_Big_Unsigned("16#57C19F8F7866F8633AC1D25B92FC83B4#"); 
Y : Big_Unsigned := To_Big_Unsigned("16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60#"); 

x := X * Y; 
Put_Line(X); 

end Test.Big_Numbers; 
 
Best regards 
    Christian 
+0

dzięki dużo! To jest o wiele więcej odpowiedzi, niż miałam nadzieję ... Sprawdzę to. – Arne

+0

Dobra odpowiedź, Christian. Poszedłem dalej i zweryfikowałem twoje dodatkowe strony internetowe i zamieniłem je w linki dla ciebie. Mam nadzieję, że dodatkowe 10 punktów z mojego programu pomoże szybciej wyprowadzić cię z niezaufanej ziemi noobów. –

1

Z czego wnoszę, każdy kompilator Ada pochodzi z dowolnej długości arytmetycznej zabudowy. Wymagane jest obsługiwanie nazwanych liczb (bezterminowych stałych numerycznych) w sposób zdefiniowany przez język.

W związku z tym, szkoda, że ​​standard nie zapewniał nam standardowego dostępu do tego urządzenia. Z drugiej strony, użyteczne dla tego, czego potrzebuje kompilator i użyteczne do ogólnego użytku, mogą być często dwie różne rzeczy.