Произвольная длина целого числа в Аде - PullRequest
6 голосов
/ 21 августа 2009

В настоящее время я учу себя Аде, и хотя я мог бы начать с решения некоторых более традиционных проблем, чтобы начать.

Более конкретно, я пытаюсь вычислить факториал n !, тогда как n> 100. Моя реализация до сих пор:

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;

Проблема, очевидно, в том, что даже Long_Long_Integer может быть слишком мал для этого и выдает исключение CONTRAINT_ERROR для n> 20.

Существует ли пакет, который реализует целые числа произвольного размера?

Спасибо!

PS: я выбрал рекурсию, потому что я хотел исследовать циклы в этом упражнении. Но в противном случае, пожалуйста, прокомментируйте все аспекты кода (стиль, лучшие практики, ошибки ..)

Ответы [ 2 ]

8 голосов
/ 21 августа 2009

Библиотека шифрования Ada поддерживает большие числа без знака (Big_Numbers). Вы можете скачать библиотека от http://sourceforge.net/projects/libadacrypt-dev/. Я рекомендую проверить SVN. Функция умножения больших чисел в текущем выпуске есть небольшая ошибка.

Вы можете скомпилировать библиотеку с помощью текущего компилятора GNAT с сайта AdaCore Libre .

Библиотека не будет компилироваться в gcc-4.3 или gcc-4.4 из-за ошибки в gcc .

Наконец, я приведу небольшой пример, как умножить два 512-битных Big_Numbers из 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
1 голос
/ 24 августа 2009

Из того, что я понял, каждый компилятор Ada поставляется со встроенной арифметикой произвольной длины. Требуется поддерживать именованные числа (числовые константы без ввода) так, как это определено в языке.

Учитывая то, что, к сожалению, стандарт не предоставил нам стандартный доступ к этому средству. Опять же, пригодный для использования для того, что нужно компилятору, и пригодный для общего использования, часто это две разные вещи.

...