Книга: UNIX — универсальная среда программирования

Приложение 2 Справочное руководство по hoc

Приложение 2

Справочное руководство по hoc

Hoc — диалоговый язык для арифметики с плавающей точкой

Б. КерниганР. Пайк

РЕЗЮМЕ

Hoc — это простой программируемый интерпретатор для выражений с плавающей точкой. Он обеспечивает поток управления в стиле Си, определения функций и обычные числовые встроенные функции, такие, как косинус и логарифм.

Выражения

Hoc представляет язык выражений, во многом подобный Си: хотя он и содержит несколько управляющих операторов, большинство операторов, например присваивания, суть выражения, значения которых не принимаются во внимание. Так, оператор присваивания = присваивает значение своей правой части левому операнду и вырабатывает значение, используемое в многократном присваивании. Грамматика выражений имеет вид:

выражение : число
 | переменная
 | (выражение)
 | выражение бинарная_операция выражение
 | унарная_операция выражение
 | функция(аргументы)

Числа представляются с плавающей точкой. Формат ввода распознается с помощью scanf(3): цифры, десятичная точка, цифры, е или E, показатель степени со знаком. Должна присутствовать по крайней мере одна цифра или десятичная точка; другие компоненты являются необязательными.

Имена переменных формируются из букв, за которыми следуют строки букв и цифр. Здесь бинарная_операция означает двуместные операции, такие, как сложение или логическое сравнение, а унарная_операция — две операции отрицания: '!' (логическое отрицание НЕ) и (арифметическое отрицание, перемена знака). Все операции перечислены в табл. П.2.1.

^ Возведение в степень (FORTRAN **), правоассоциативна
! - Одноместные логическое и арифметическое отрицания
* / Умножение, деление
+ - Сложение, вычитание
> >= Операции отношения: больше, больше или равно
< <= Меньше, меньше или равно
== != Равно, не равно (все отношения одинакового приоритета)
&& Логическое И (оба операнда всегда вычисляются)
|| Логическое ИЛИ (оба операнда всегда вычисляются)
= Присваивание, правоассоциативна

Таблица П.2.1. Операции по порядку уменьшения приоритета

Функции, как описывается ниже, могут быть определены пользователем. Аргументы функций — это выражения, разделяемые запятыми. В табл. П.2.2 перечислено несколько встроенных функций, имеющих по одному аргументу.

abs(x) Абсолютная величина x
atan(x) Арктангенс x
cos(x) Косинус x
exp(х) Экспонента x
int(x) Целая часть x, усеченная в сторону нуля
log(x) Натуральный логарифм x
log10(x) Десятичный логарифм x
sin(x) Синус x
sqrt(x) Корень квадратный из x

Таблица П.2.2. Встроенные функции

Логические выражения имеют значения 1 (истина) и 0 (ложь). Как и в Си, любое ненулевое значение означает истину. При всех операциях над числами с плавающей точкой сравнения на равенство могут быть неточными. Кроме того, hoc имеет несколько встроенных констант, приведенных в табл. П.2.3.

DEG 57.2957795130823208768 180/?, градусы на радианы
E 2.71828182845904523536 е, основание натуральных логарифмов
GAMMA 0.57721566490153286060 ?, константа Эйлера-Масчерони
PHI 1.61803398874989484820 (?5+1)/2, золотое сечение
PI 3.14159265358979323846 ?, круговое трансцендентное число

Таблица П.2.3. Встроенные константы

Операторы и поток управления

Операторы hoc имеют следующую грамматику:

оператор : выражение
 | переменная выражение
 | процедура (список, аргументов)
 | while (выражение) оператор
 | if (выражение) оператор
 | if (выражение) оператор else оператор
 | список_операторов
 | print список_выражений
 | return возможное_выражение
список_операторов : (пусто)
 | список_операторов оператор

Присваивание распознается по умолчанию как оператор, а не как выражение, поэтому после ввода в диалоге присваиваний их значения не печатаются.

Отметим, что символ ; не является для hoc специальным: оператор оканчивается символом перевода строки. Это обусловливает некоторые особенности. Ниже показан допустимый оператор if:

if (x < 0) print(у) else print (z)
if (x < 0) {
 print(y)
} else {
 print(z)
}

Во втором примере скобки не обязательны: символ перевода строки после if оканчивал бы оператор и вызывал бы синтаксическую ошибку там, где опущены скобки.

Синтаксис и семантика средств управления в hoc в основном те же, что и в Си. Одинаковы также while и if, однако в hoc нет операторов break и continue.

Ввод и вывод: read и print

Функция ввода read (читать) имеет, подобно другим встроенным функциям, один аргумент: однако он не является выражением: это имя переменной. Следующее число, как определено выше, читается из стандартного входного потока и присваивается поименованной переменной. Функция read возвращает значения 1 (истина), если величина была прочитана, и 0 (ложь), если read встретила конец файла либо ошибку.

Выходной поток порождается оператором print. Аргументы print составляют разделяемый запятыми список выражений и строк, взятых в кавычки, как в Си. Символы перевода строки должны добавляться: print их никогда автоматически не вводит.

Отметим, что read есть специальная встроенная функция и поэтому получает один аргумент в скобках, тогда как print оператор, получающий список, разделяемый запятыми без скобок:

while (read (x)) {
 print "value is", x, "n"
}

Функции и процедуры

Функции и процедуры в hoc различаются, хотя и определены одним и тем же механизмом. Это различие введено просто для контроля ошибок во время исполнения: возврат значения является ошибкой для процедуры, для функции же ошибочно не возвращать значения.

Синтаксис определения таков:

function: func имя () оператор
procedure: proc имя() оператор

Здесь имя может быть именем некоторой переменной встроенные функции исключаются. Определение, вплоть до открывающейся скобки оператора, должно помещаться на одной строке, как в приведенном выше операторе if.

В отличие от Си тело функции или процедуры может быть любым оператором, не обязательно составным (в скобках). Поскольку символ ; не имеет своего значения в hoc, пустое тело процедуры формируется пустой парой скобок.

Функции и процедуры при вызовах могут получать аргументы, отделенные запятыми. На аргументы ссылаются так же, как в shell: $3 относится к третьему, индексируемому, начиная с единицы, аргументу. Они передаются значениями и внутри функций семантически эквивалентны переменным. Ссылка на аргумент с помощью числа, превышающего число аргументов, переданных процедуре, считается ошибкой. Контроль ошибок динамический, поскольку подпрограмма может иметь переменное число параметров, если ее начальные аргументы влияют на это число (см. функцию printf в Си).

Функции и процедуры могут быть рекурсивными, но стек имеет ограниченную глубину (около сотни вызовов).

Примеры

• Ниже показано определение функции Аккерманна в hoc:

$ hoc
time ack() {
 if ($1 == 0) return $2+1
 if ($2 ==0) return ack($1 - 1, 1)
 return ack($1 - 1, ack($1, $2 - 1))
}
ack(3,2)
 29
ack(3,3)
 61
ack(3,4)
 hoc: стек слишком велик (строка 8)
...

• Формула Стирлинга:


$ hoc
func stirl() {
 return sqrt(2 * $1 * PI) * ($1 / E) ^ $1 * (1 + 1 / (12 * $1))
}
stirl(10) 3628684.7
stirl(20) 2.4328818e+18

• Функция факториал n!

func fac() if ($1 <= 0) return 1 else return $1 * fac($1 - 1)

Отношение факториала к приближению Стирлинга:

i = 9
while ((i = i + 1) <= 20) {
 print i, " ", fac(i)/stirl(i), "n"
}
10 1.0000318
11 1.0000265
12 1.0000224
13 1.0000192
14 1.0000166
15 1.0000146
16 1.0000128
17 1.0000114
18 1.0000102
19 1.0000092
20 1.0000083

Оглавление книги


Генерация: 1.864. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз