2009-08-20 6 views
6

Je m'apprends actuellement à Ada et bien que je puisse commencer en abordant certains des problèmes plus classiques pour commencer.Longueur arbitraire entier dans Ada

Plus précisément, j'essaie de calculer la factorielle n !, alors que n> 100. Ma mise en œuvre jusqu'à présent est:

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; 

Le problème est évidemment que même Long_Long_Integer est peut trop petit pour cela et jette une exception CONTRAINT_ERROR pour n> 20.

Existe-t-il un package qui implémente des entiers de taille arbitraire?

Merci! PS: J'ai opté pour la récursivité parce que je voulais explorer les boucles dans cet exercice. Sinon, veuillez commenter tous les aspects du code (style, meilleures pratiques, erreur ..)

Répondre

8

La bibliothèque de cryptage Ada prend en charge les grands nombres non signés (Big_Numbers). Vous pouvez télécharger la lib de http://sourceforge.net/projects/libadacrypt-dev/. Je recommande de vérifier le svn. La fonction de multiplication Big_Numbers de la version actuelle présente un bogue mineur.

Vous pouvez compiler le fichier lib avec le compilateur GNAT actuel à partir de the AdaCore Libre site.

La bibliothèque ne compilera pas sous gcc-4.3 ou gcc-4.4 en raison de a bug in gcc.

Enfin, je vais vous donner un petit exemple sur la façon de multiplier deux Big_Numbers 512 bits à partir 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

merci beaucoup! C'est beaucoup plus d'une réponse que j'espérais obtenir .. Je vais vérifier. – Arne

+0

Bonne réponse, Christian. Je suis allé de l'avant et vérifié vos pages Web supplémentaires et les a transformés en liens pour vous. Espérons que les 10 points supplémentaires de mon upvote vous aideront à vous propulser plus tôt des terres noob non fiables. –

1

D'après ce que je comprends, chaque compilateur Ada est livré avec l'arithmétique de longueur arbitraire intégré. Il est nécessaire de prendre en charge les nombres nommés (constantes numériques sans typage) de la façon dont le langage les a définis. Compte tenu de cela, il est dommage que la norme ne nous fournisse pas aux utilisateurs un accès standard à cette installation. Là encore, utilisable pour ce dont le compilateur a besoin, et utilisable pour un usage général peut souvent être deux choses différentes.

Questions connexes