增加整数大小/避免整数溢出?
increase integer size / avoid integer overflow?
在 FORTRAN 中,我可以将整数的声明更改为 integer(kind = 8)
并且它有效。
如何在 Ada 中做类似的事情?
我的程序正在处理非常大的数字,当它变得非常大时它会给我一些负数。
我试过:
with ada.text_io; use ada.text_io;
with ada.integer_text_io; use ada.integer_text_io;
with multiplication_io; use multiplication_io;
procedure multiplication is
type unsigned is range 0 .. 2**32-1;
multiplier, multiplicand : unsigned;
begin
put_line("multiplier?");
get(multiplier);
end multiplication;
但我收到以下错误:
multiplication.adb:12:05: no candidate interpretations match the actuals:
multiplication.adb:12:05: missing argument for parameter "Item" in call to "get" declared at a-tiinio.ads:70, instance at a-inteio.ads:18
multiplication.adb:12:05: missing argument for parameter "Item" in call to "get" declared at a-tiinio.ads:50, instance at a-inteio.ads:18
multiplication.adb:12:05: missing argument for parameter "Item" in call to "get" declared at a-textio.ads:239
multiplication.adb:12:05: missing argument for parameter "Item" in call to "get" declared at a-textio.ads:205
multiplication.adb:12:09: expected type "Standard.Integer"
multiplication.adb:12:09: found type "unsigned" defined at line 7
multiplication.adb:12:09: ==> in call to "Get" at a-tiinio.ads:55, instance at a-inteio.ads:18
multiplication.adb:12:09: ==> in call to "Get" at a-textio.ads:240
multiplication.adb:12:09: ==> in call to "Get" at a-textio.ads:206
gnatmake: "src/multiplication.adb" compilation error
Makefile:18: recipe for target 'default' failed
make: *** [default] Error 4
定义一个范围为0到2**32的整数类型:
type My_Integer is range 0 .. 2**32;
您不需要指定它派生自哪个预定义整数类型;让编译器为您处理。
顺便说一下,您可能想要:
type My_Integer is range 0 .. 2**32-1;
如果它应该占用32位。
您还需要决定是要普通整数类型还是模块化类型。无论您选择什么范围,它仍然有可能溢出,其结果取决于您是否禁用了范围检查。
对于您现在添加到问题中的示例代码,您需要为您的整数类型实例化 Integer_IO
:
package Unsigned_IO is new Ada.Text_IO.Integer_IO(unsigned);
-- ...
Unsigned_IO.Get(Multiplier);
你不告诉我们 multiplication_io
是什么;但是如果要 i/o 与乘法相关(无论可能是什么!)你 可能 想要添加 use multiplication_io;
.
我试过了
with Ada.Text_IO; use Ada.Text_IO;
procedure Multiplication is
type Unsigned is range 0 .. 2**32-1;
Multiplier, Multiplicand : Unsigned;
package Multiplication_IO is new Ada.Text_IO.Integer_IO (Unsigned);
use Multiplication_IO;
begin
Put_Line("multiplier?");
Get(Multiplier);
end Multiplication;
它编译得很好。
当然,我的 Multiplication_IO
应该被称为 Unsigned_IO
,正如@KeithThompson 所建议的。关键是,不管它叫什么,都是为了 Unsigned
值;它不适用于 Integer
。你写了 get(multiplier);
,而编译器唯一能看到的 get
是 Integer_Text_IO
中的那个 Integer
。您需要阅读有关 Ada 和类型的内容! adaic.org 的其中一本电子书将是一个开始。
对于更大的数字,您可以查看 Long_Integer
:在 GNAT 中,它是
type Long_Integer is range -(2 **63) .. +(2 **63 - 1);
for Long_Integer'Size use 64;
如果计算的 结果 符合常规整数(但计算可能会溢出),您可能需要查看 GNAT 溢出消除 (http://docs.adacore.com/gnat_ugn-docs/html/gnat_ugn/gnat_ugn/gnat_and_program_execution.html#management-of-overflows-in-gnat)。例如。使用 pragma Overflow_Mode(常规 => 消除);
在 FORTRAN 中,我可以将整数的声明更改为 integer(kind = 8)
并且它有效。
如何在 Ada 中做类似的事情?
我的程序正在处理非常大的数字,当它变得非常大时它会给我一些负数。
我试过:
with ada.text_io; use ada.text_io;
with ada.integer_text_io; use ada.integer_text_io;
with multiplication_io; use multiplication_io;
procedure multiplication is
type unsigned is range 0 .. 2**32-1;
multiplier, multiplicand : unsigned;
begin
put_line("multiplier?");
get(multiplier);
end multiplication;
但我收到以下错误:
multiplication.adb:12:05: no candidate interpretations match the actuals:
multiplication.adb:12:05: missing argument for parameter "Item" in call to "get" declared at a-tiinio.ads:70, instance at a-inteio.ads:18
multiplication.adb:12:05: missing argument for parameter "Item" in call to "get" declared at a-tiinio.ads:50, instance at a-inteio.ads:18
multiplication.adb:12:05: missing argument for parameter "Item" in call to "get" declared at a-textio.ads:239
multiplication.adb:12:05: missing argument for parameter "Item" in call to "get" declared at a-textio.ads:205
multiplication.adb:12:09: expected type "Standard.Integer"
multiplication.adb:12:09: found type "unsigned" defined at line 7
multiplication.adb:12:09: ==> in call to "Get" at a-tiinio.ads:55, instance at a-inteio.ads:18
multiplication.adb:12:09: ==> in call to "Get" at a-textio.ads:240
multiplication.adb:12:09: ==> in call to "Get" at a-textio.ads:206
gnatmake: "src/multiplication.adb" compilation error
Makefile:18: recipe for target 'default' failed
make: *** [default] Error 4
定义一个范围为0到2**32的整数类型:
type My_Integer is range 0 .. 2**32;
您不需要指定它派生自哪个预定义整数类型;让编译器为您处理。
顺便说一下,您可能想要:
type My_Integer is range 0 .. 2**32-1;
如果它应该占用32位。
您还需要决定是要普通整数类型还是模块化类型。无论您选择什么范围,它仍然有可能溢出,其结果取决于您是否禁用了范围检查。
对于您现在添加到问题中的示例代码,您需要为您的整数类型实例化 Integer_IO
:
package Unsigned_IO is new Ada.Text_IO.Integer_IO(unsigned);
-- ...
Unsigned_IO.Get(Multiplier);
你不告诉我们 multiplication_io
是什么;但是如果要 i/o 与乘法相关(无论可能是什么!)你 可能 想要添加 use multiplication_io;
.
我试过了
with Ada.Text_IO; use Ada.Text_IO;
procedure Multiplication is
type Unsigned is range 0 .. 2**32-1;
Multiplier, Multiplicand : Unsigned;
package Multiplication_IO is new Ada.Text_IO.Integer_IO (Unsigned);
use Multiplication_IO;
begin
Put_Line("multiplier?");
Get(Multiplier);
end Multiplication;
它编译得很好。
当然,我的 Multiplication_IO
应该被称为 Unsigned_IO
,正如@KeithThompson 所建议的。关键是,不管它叫什么,都是为了 Unsigned
值;它不适用于 Integer
。你写了 get(multiplier);
,而编译器唯一能看到的 get
是 Integer_Text_IO
中的那个 Integer
。您需要阅读有关 Ada 和类型的内容! adaic.org 的其中一本电子书将是一个开始。
对于更大的数字,您可以查看 Long_Integer
:在 GNAT 中,它是
type Long_Integer is range -(2 **63) .. +(2 **63 - 1);
for Long_Integer'Size use 64;
如果计算的 结果 符合常规整数(但计算可能会溢出),您可能需要查看 GNAT 溢出消除 (http://docs.adacore.com/gnat_ugn-docs/html/gnat_ugn/gnat_ugn/gnat_and_program_execution.html#management-of-overflows-in-gnat)。例如。使用 pragma Overflow_Mode(常规 => 消除);