Спецификация программ и преобразователь предикатов
Важнейший для дальнейшего изучения материал этого параграфа в более подробном изложении можно найти в книге [4]. Полезным будет также и знакомство с подходом учебного пособия [9].
Предикаты и документирование программ
Как уже отмечалось выше, предикаты нам нужны прежде всего для того, чтобы иметь возможность ясно и недвусмысленно формулировать определенные утверждения о программах и программных переменных. Сейчас мы рассмотрим ряд примеров подобного типа.
Задача 6.1. Запишите предикат, утверждающий, что если , а , то .
Решение. В данном случае все очевидно: .
Задача 6.2. Запишите предикат, утверждающий, что ни одно из следующих утверждений не является истинным: , и .
Решение Это задание тоже не является сложным. Вот несколько эквивалентных между собой решений: , и . Так как обычно нужно предъявить максимально простой предикат, то будем считать ответом последний из них — .
В ряде последующих задач нам придется иметь дело с массивами, поэтому договоримся о следующих обозначениях: будем обозначать вырезку из массива , в которой содержатся все элементы данного массива с индексами от до включительно, символом . В случаях, когда , или , вырезка представляет из себя пустое множество.
Задача 6.3.Запишите предикат, утверждающий, что для массива длины все элементы вырезки являются нулевыми.
Решение. Используем квантор всеобщности: .
Задача 6.4.Запишите предикат, утверждающий, что для массива длины ни один из элементов вырезки не нулевой.
Решение. Переформулировав данное высказывание (все элементы вырезки не нулевые), запишем ответ в следующем виде: .
Задача перевода высказывания с естественного языка на язык предикатов не всегда является однозначной, но именно это и является одной из причин его использования. Вот пример.
Задача 6.5. Запишите предикат, утверждающий, что для массива длины некоторые из элементов вырезки нулевые.
Решение. Данное высказывание можно понимать двояко: оно может означать, что в вырезке существует хотя бы один нулевой элемент, а может значить и то, что в ней как минимум два нулевых элемента. Вот ответы для каждого из этих вариантов трактовки задачи: и .
Вот аналогичные задачи из области математики.
Задача 6.6. Запишите предикат, который утверждает, что функция является сюръективной и отрицание этого факта. Упростите получившиеся предикаты, если это возможно.
Решение. В соответствии с определением сюръективности имеем . Построим отрицание и упростим его в соответствии с законами эквивалентности. .
Задача 6.7. Запишите предикат, который утверждает, что функция все элементы, не превосходящие трех, не увеличивает, и отрицание этого факта. Упростите получившиеся предикаты, если это возможно.
Решение. . Его отрицание можно упростить: .
В текст программы зачастую полезно включать предикаты, которые позволяли бы человеку или компьютеру проверять корректность хода выполнения программы. В тех случаях, когда подобные утверждения предназначены только для человека, они оформляются в виде комментариев.
Часто, однако, полезно поручить проверку истинности предикатов в процессе выполнения программы непосредственно компьютеру. В различных языках программирования эта возможность реализована по-разному. Например, в программах на языке C можно использовать макрос assert(P), который в случае ложности его аргумента (предиката P ) немедленно прекращает выполнение программы, сообщая о причине этого.
Механизм работы с исключениями и оператор if позволяют легко реализовать аналогичную конструкцию в языке Java. Вот простейший пример.
Задача 6.8. Напишите программу, содержащую проверку истинности утверждения о положительности введенного с клавиатуры целого числа.
Текст программы
public class Assert { public static void main(String[] args) throws Exception { int n = Xterm.inputInt("Введите n -> "); if (n <= 0) throw new Exception("n <= 0"); Xterm.println("n = " + n); } }
При вводе неположительного числа программа прекращает свое выполнение и печатает следующий текст:
java.lang.Exception: n<=0 at Assert.main(Assert.java:4)
Богатые возможности работы с исключениями, имеющиеся в языке, позволяют реализовать гораздо более изощренные способы проверки истинности предикатов, нежели использованный в программе простейший вариант возбуждения исключения типа Exception без попыток его последующей обработки. Эти возможности, однако, не будут рассматриваться в нашем курсе.