Прежде всего, я предполагаю, что функция noPrimos
вернет True
, только если список lista
не содержит простых чисел. При этом я немного озадачен некоторыми аспектами фрагмента кода:
Определение типа My_Array
отсутствует.
Роль глобального экземпляра contador
(англ .: counter) не ясна из данного фрагмента кода. Написав Global=> contador
, вы заявляете, что глобальная переменная contador
будет прочитана функцией noPrimos
(см. Также здесь ), но этого не происходит, потому что локальный экземпляр 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 (spec)
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