在Ada (GNAT)中,使用pragma Overflow_Mod /无限精度中间计算



我正试图将一个(小)分子和分母转换为一个大常数分母的分子,选择被大多数小数整除,并且略低于2**63。因为这很可能溢出,我将使用pragma Overflow_Mode (eliminate)(参考GNAT 4.8手册http://gcc.gnu.org/onlinedocs/gcc-4.8.0/gnat_ugn_unw/Specifying-the-Desired-Mode.html#Specifying-the-Desired-Mode)。

with Ada.Command_Line;
with Ada.Text_IO;
procedure Example is
    pragma Overflow_Mode (Eliminated);
    Large_Composite : constant := (2 ** 7) * (3 ** 5) * (5 ** 2) * 7 
            * 11 * 13 * 17 * 19 * 23 * 29 * 31 * 37 * 41;
    type Word_Unsigned is mod 2**64;
N, D : Integer;
begin
    N := Integer'Value (Ada.Command_Line.Argument (1));
    D := Integer'Value (Ada.Command_Line.Argument (2));
    Ada.Text_IO.Put (Word_Unsigned ((N * Large_Composite) / D)'Img);
end Example;

不幸的是,当试图用"~/bin/gcc-4.8.0/bin/gnatmake -gnat12 -gnata -Wall示例编译示例代码(并且它是真实代码的蒸馏)时。Adb"(和-gnato3,尽管这对编译来说应该是多余的),编译器说:

example.adb:12:46: value not in range of type "Standard.Integer"
example.adb:12:46: static expression fails Constraint_Check
gnatmake: "example.adb" compilation error

Hrumph。我不明白Overflow_Mode做什么?有什么简单的方法来重新安排它,使其工作吗?(我可以去计划A,一个更正常的分数类,可能会或可能不会更快或计划B,只是使用浮点数和接受1/3将得到四舍五入,但我希望这是工作。适当的无限长整数支持在这里是多余的)

这不是一个完整的答案,但是使用Long_Long_Integer,它足够大,可以容纳Large_Composite,而不是Integer,可以抑制警告,并且pragma Overflow_Mode可以完成它的工作,让我使用N = 99和D = 100这样的东西并得到正确的答案。这个计算模型看起来仍然有些不一致,但至少代码是工作的。

最新更新