1

我正在尝试将(小)分子和分母转换为大常数分母的分子,选择为可被大多数小数整除并且略低于 2**63。由于这可能会溢出,我将使用 pragma Overflow_Mode(已消除)(参见 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 example.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

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

4

1 回答 1

1

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

于 2013-06-11T08:22:17.517 回答