我不知道为什么证明变量变量contador溢出时是错误的。我需要帮助。
contador: Integer;
J: Integer;
function noPrimos (lista : My_Array) return Boolean
with
Global => contador,
--Depends => ...,
Pre => True and contador < Integer'Last,
Post => (noPrimos'Result = True or noPrimos'Result = False);
FILE ADB
function noPrimos (lista : My_Array) return Boolean is
contador: Integer;
begin
for I in lista'Range loop
contador:= 0;
if lista(I) /= 1 then
for J in 1.. lista(I) loop
if lista(I) rem J = 0 then
contador := contador + 1;
end if;
end loop;
if contador <= 2 then
return false;
end if;
else
return true;
end if;
pragma Loop_Variant(Increases => I);
end loop;
return true;
end noPrimos;
问题是溢出的结果: 第2阶段的第1阶段:生成全球合同... 第2阶段的第2阶段:流程分析和证明... 15:40:中:溢出检查可能会失败(例如,当contador = 2147483647时) 47:40:中等:溢出检查可能会失败(例如,当contador = 0时)
答案 0 :(得分:3)
首先,我假设仅当列表noPrimos
不包含任何质数时,函数True
才会返回lista
。话虽这么说,但我对代码片段的某些方面感到有些困惑:
缺少My_Array
的类型定义。
从给定的代码片段中不清楚contador
的全局实例(英语:counter)的作用。通过编写Global=> contador
,您声明全局变量contador
将由函数noPrimos
(另请参见here)读取,但这不会发生,因为本地实例contador
中的{}遮盖了contador
的全局实例。
尚不清楚全局定义变量J
的原因,您可以忽略它。
前提条件True
(在布尔运算符and
的左侧)很简单,可以省略。
后置条件指出noPrimos
的结果可以是True
或False
。这很简单,因为noPrimos
返回一个布尔值,因此可以省略。后置条件应在给出其输入的情况下说明函数的预期结果。
循环变量pragma Loop_Variant(Increases => I);
很小,因为变量I
将因for循环的定义而增加。因此可以省略循环变量。
下面是函数No_Primes
的示例,该函数在给定列表L
中搜索素数,如果找不到则返回True
。在GNAT CE 2019中得到了证明:
primes.ads (规范)
package Primes with SPARK_Mode is
type List is
array (Natural range <>) of Positive;
--
-- Returns True if N is a prime number (or False otherwise).
--
function Is_Prime (N : Positive) return Boolean
with
Global => null,
Post => Is_Prime'Result =
(if N = 1 then False
else (for all I in 2 .. N - 1 => N rem I /= 0));
--
-- Returns True if list L does not contain any prime numbers (or False otherwise).
--
function No_Primes (L : List) return Boolean
with
Global => null,
Post => No_Primes'Result =
(for all I in L'Range => Is_Prime (L (I)) = False);
end Primes;
primes.adb (正文)
package body Primes with SPARK_Mode is
--------------
-- Is_Prime --
--------------
function Is_Prime (N : Positive) return Boolean is
begin
if N = 1 then
return False;
else
for I in 2 .. N - 1 loop
if N rem I = 0 then
return False;
end if;
pragma Loop_Invariant
(for all J in 2 .. I => N rem J /= 0);
end loop;
end if;
return True;
end Is_Prime;
---------------
-- No_Primes --
---------------
function No_Primes (L : List) return Boolean is
begin
for I in L'Range loop
if Is_Prime (L (I)) then
return False;
end if;
pragma Loop_Invariant
(for all J in L'First .. I => Is_Prime (L (J)) = False);
end loop;
return True;
end No_Primes;
end Primes;
一个小型测试程序( main.adb )
with Ada.Text_IO; use Ada.Text_IO;
with Primes; use Primes;
procedure Main is
-- Some test vectors.
L1 : List := (1 => 1); -- Expect TRUE : 1 is not a prime.
L2 : List := (1, 2, 3, 5, 7); -- Expect FALSE : All are prime except 1.
L3 : List := (2, 3, 5, 7); -- Expect FALSE : All are prime.
L4 : List := (1, 4, 6, 8, 9); -- Expect TRUE : None are prime.
L5 : List := (4, 6, 8, 9); -- Expect TRUE : None are prime.
L6 : List := (3, 4, 5); -- Expect FALSE : 3 and 5 are prime.
begin
Put_Line ("No_Primes (L1) = " & Boolean'Image (No_Primes (L1)));
Put_Line ("No_Primes (L2) = " & Boolean'Image (No_Primes (L2)));
Put_Line ("No_Primes (L3) = " & Boolean'Image (No_Primes (L3)));
Put_Line ("No_Primes (L4) = " & Boolean'Image (No_Primes (L4)));
Put_Line ("No_Primes (L5) = " & Boolean'Image (No_Primes (L5)));
Put_Line ("No_Primes (L6) = " & Boolean'Image (No_Primes (L6)));
end Main;
收益
No_Primes (L1) = TRUE
No_Primes (L2) = FALSE
No_Primes (L3) = FALSE
No_Primes (L4) = TRUE
No_Primes (L5) = TRUE
No_Primes (L6) = FALSE