2009-08-20 15 views
6

Actualmente me estoy enseñando a mí mismo Ada y aunque podría comenzar abordando algunos de los problemas más convencionales para comenzar.Número de longitud arbitrario en Ada

Más específicamente, trato de calcular el factorial n !, mientras que n> 100. Mi aplicación hasta ahora es:

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; 

El problema es, obviamente, que incluso puede Long_Long_Integer es demasiado pequeño para esto y emite una excepción CONTRAINT_ERROR para n> 20.

¿Hay algún paquete que implemente enteros de tamaño arbitrario?

Gracias!

PD: Opté contra la recursividad porque quería explorar los bucles en este ejercicio. De lo contrario, comentar todos los aspectos del código (estilo, mejores prácticas, error ...)

Respuesta

8

Ada Crypto Library admite números grandes sin firmar (Big_Numbers). Puede descargar lib desde http://sourceforge.net/projects/libadacrypt-dev/. Recomiendo ver el svn. La función de multiplicación Big_Numbers de la versión actual tiene un error menor.

Puede compilar la lib con el compilador GNAT actual desde the AdaCore Libre site.

La lib no se compilará bajo gcc-4.3 o gcc-4.4 debido a a bug in gcc.

Finalmente, le daré un pequeño ejemplo de cómo multiplicar dos Big_Numbers de 512 bits de 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

gracias mucho! Esa es una respuesta mucho más de lo que esperaba obtener ... Lo comprobaré. – Arne

+0

Buena respuesta, Christian. Seguí adelante y verifiqué sus páginas web adicionales y las convertí en enlaces para usted. Afortunadamente, los 10 puntos extra de mi voto ascendente ayudarán a expulsarlo de la tierra de los nobles que no son de confianza antes. –

1

Por lo que sé, cada compilador de Ada viene con longitud arbitraria aritmética incorporada. Se requiere que admita números con nombre (constantes numéricas sin tipo) de la forma en que el lenguaje los ha definido.

Dado que, es una pena que la norma no nos proporcione a los usuarios acceso estándar a esa instalación. Por otra parte, utilizable para lo que el compilador necesita, y utilizable para uso general a menudo puede ser dos cosas diferentes.

Cuestiones relacionadas