Главная » Программирование для UNIX » Руководство по HOC

0

Hoc – интерактивный язык для математических выражений с плавающей точкой

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

АННОТАЦИЯ

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

1.      Выражения

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

expr:

number

|

variable

|

( expr )

|

expr binop expr

|

unop expr

|

function ( arguments )

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

Имена переменных образованы буквой, за которой следует буквенноцифровая строка. Бинарные операции, такие как сложение или логи ческое сравнение, обозначены binop; unop – это два оператора отрицания: ! (логическое отрицание, «не»)  и – (арифметическое отрицание, изменение знака). Операторы перечислены в табл. 1.

Таблица 1. Операторы в порядке понижения приоритета

Оператор

Действие

^

! –

* /

+ –

> >=

< <=

== !=

&&

||

=

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

сложение, вычитание

операторы отношения: больше, больше или равно меньше, меньше или  равно

равно, не равно (все с одинаковым приоритетом) логическое И (всегда оцениваются оба операнда) логическое ИЛИ  (всегда оцениваются оба операнда) присваивание, ассоциативно справа

Функции, как будет рассказано дальше, могут быть  определены поль зователем. Аргументами функций являются выражения, разделенные запятыми.  Существуют и  встроенные функции  (все  они  принимают только один аргумент), они описаны в табл. 2.

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

Функция       Возвращаемое значение abs(x)              |x|, абсолютная величина x atan(x)            арктангенс x

cos(x)              cos(x), косинус x

exp(x)              ex, экспонента x

int(x)            целая часть x, дробная часть  отбрасывается

log(x)           log(x), логарифм x по основанию e log10(x)         log10(x), логарифм x по основанию 10 sin(x)           sin(x), синус  x

sqrt(x)            корень квадратный из x; x1/2

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

В hoc есть  также несколько встроенных  констант, представленных в табл. 3.

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

Константа

Значение

Пояснение

DEG E GAMMA PHI

PI

57,29577951308232087680

2,71828182845904523536

0,57721566490153286060

1,61803398874989484820

3,14159265358979323846

180/π, градусов в радиане

e, основание натурального логарифма

γ, константа Эйлера–Маскерони (   5+1)/2, золотое сечение

π, отношение длины окружности к ее

диаметру

2.    Операторы и управляющая логика

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

stmt:

|

expr

variable = expr

|

|

|

|

|

|

|

procedure ( arglist )

while ( expr  ) stmt if ( expr ) stmt

if ( expr ) stmt else stmt

{ stmtlist }

print expr5list

return optional5expr

stmtlis

|

(nothing) stmlist  stmt

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

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

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

print(y)

} else { print(z)

}

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

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

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

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

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

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

while  (read(x)) {

print  "value  is ",  x, "\n"

}

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

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

Синтаксис определения выглядит следующим образом:

function:               func  name() stmt procedure:             proc  name()  stmt

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

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

При вызове функции и процедуры могут принимать аргументы, разделенные запятыми. Аргументы указываются так  же, как и в оболочке:

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

Функции и процедуры могут  быть рекурсивными, но размер стека ограничен (около сотни  вызовов). Покажем это на примере функции Аккермана (Ackermann), определенной в hoc:

$   hoc

func    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:  stack too  deep near  line 8

5.    Примеры

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

$ hoc

func  stirl()  {

n! ∼

2nπ(n e )n⎛1 +

1 -⎞

12n

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

Источник: Керниган Б., Пайк Р., UNIX. Программное окружение. – Пер. с англ. – СПб: Символ-Плюс, 2003. – 416 с., ил.

По теме:

  • Комментарии