Арифметический язык произвольной точности "Bench calculator" (POSIX)
bc [-l] [файл...]
ЗОСРВ «Нейтрино»
aarch64, arm, armv7, e2k, mips, ppc, x86
Утилита bc является интерактивным программируемым калькулятором, который поддерживает законченный набор контролирующих структур и функций.
Для утилиты bc предусмотрена поддержка 26 функций, 26 простых переменных и 26 переменных типа "массив". Каждый массив может содержать до 2048 элементов. Кроме того, утилита выполняет арифметические операции с использованием системы счисления с основанием 100 и с возможностью определения точности пользователем. Если указана точность, то числа строго соответствуют ей в отличие от двоичного представления с плавающей запятой, где ошибки округления могут снизить точность. Для утилиты также предусмотрена поддержка различных оснований систем счисления, что обеспечивает возможность простого преобразования чисел из одной системы счисления в другую.
Поддерживается большое количество общих конструкций языков программирования, в т.ч. следующие:
Для утилиты bc не предусмотрена поддержка обработки символов или строк. Синтаксис утилиты bc заимствован из языка C, но не является языком программирования.
Рассмотрим очень простую программу bc:
"hello, world\n"
При выполнении этой программы выражение "hello, world" отображается на экране с символом новой строки. В общем случае результат любого выражения, не назначенного переменной или не используемого в управляющей структуре, отображается на экране. Например, следующий оператор:
5^2
обеспечивает возврат утилитой bc результата 25.
Следует отметить, что знак вставки (^
) представляет собой оператор возведения в степень целого числа: выражение a^b соответствует возведению переменной a в степень b, где значение b округляется до целого числа в диапазоне от -2^31 до +2^31. Все "обычные" арифметические операторы (+
, -
, *
, /
, %
) также доступны, но оператор %
означает остаток, а не модуль.
Основания систем счисления
Две специальные встроенные переменные обеспечивают возможность выбора оснований систем счисления, используемых для вводимых и выводимых чисел:
При распознавании чисел основание системы счисления для вводимых чисел определяет значимость каждой цифры. Пример. 66 в случае основания десятичной системы счисления имеет следующее значение:
6 × 10^0 = 6 + 6 × 10^1 = 60 -- 66
Тогда как в случае основания восьмеричной системы счисления значение следующее:
6 × 8^0 = 6 + 6 × 8^1 = 48 -- 54
Следует отметить, что шестнадцатеричные числа распознаются в различных основаниях систем счисления и в зависимости от оснований систем счисления их значения изменяются. Например, число FF является действительным в случае основания десятичной системы счисления и ему соответствует десятичное значение 165:
F(=15) × 10^0 = 15 + F(=15) × 10^1 = 150 --- 165
В результате установки основания системы счисления для выводимых чисел может использоваться один из двух числовых форматов:
3 1
что следует интерпретировать как:
1 × 20^0 = 1 + 3 × 20^1 = 60 -- 61
Переменные
Для утилиты bc предусмотрена поддержка 26 простых переменных, именуемых от a до z (регистр учитывается), и 26 массивов, также именуемых от a до z. Выбор простой переменной или массива определяется контекстом. Для всех переменных выполняется автоматическая инициализация с присвоением значения 0, и они всегда являются доступными (т.е. операторы объявления отсутствуют).
Функциями могут создаваться локальные переменные (с помощью оператора auto), обеспечивающие скрытие глобальных переменных с аналогичными именами во время выполнения функции. Размер массивов ограничен 2048 элементами. На переменные можно делать ссылки (правая часть оператора) или присваивать их (левая часть оператора).
Операторы присваивания
Операторы присваивания имеют много разновидностей, как и в языке C. Пример:
a += x
означает то же самое, что и выражение:
a = a + x
Для всех бинарных операторов предусмотрен соответствующий оператор присваивания.
В выражении присваивания (например, a=10) значение находится в правой части. Это новое значение переменной a. Таким образом,
a = b = 10
обеспечивает присваивание значения 10 переменной b с последующим присваиванием значения переменной b переменной a.
Операторы инкремента и декремента могут применяться только для переменных. Выражение
b = a++
с семантической точки зрения аналогично
b = a; a = a + 1;
А выражение
b = ++a
с семантической точки зрения аналогично
a = a + 1; b = a;
В следующей таблице приведена сводная информация по старшинству и ассоциативности операторов:
Оператор | Ассоциативность | Класс |
---|---|---|
++ , -- | Неассоциативный | (инкpемент, декремент) |
- | Справа налево | (одинарный минус) |
^ | Справа налево | (возведение в степень) |
* , / , % | Слева направо | (мультипликативный) |
+ , - | Слева направо | (аддитивный) |
== , <= , >= , != , < , | Слева направо | (сравнительный) |
= , += , -= , *= , /= , %= , ^= | Справа налево | (присваивание) |
Условный оператор if
Для условного оператора if используется следующий формат:
if (выражение) оператор
Оператор выполняется, только если результат вычисления выражения выражение не равен нулю. Последующие операторы выполняются вне зависимости от значения, которое принимает выражение.
if (i > 2047) {"i выходит за пределы массива"i = 2047; /* предельное значение индекса */}a[i] /* всегда выводить значение */
Операторы цикла
Для утилиты bc предусмотрена поддержка двух операторов цикла: while и for. В обеих этих структурах break означает "немедленный выход из цикла", а continue означает "считайте, что выполнение оператора оператор закончено".
Для оператора while используется следующий общий формат:
while (выражение) оператор
Выполнение оператора осуществляется в соответствии со следующим алгоритмом:
В операторе while инструкции continue и break аналогичны действиям "Перейти к шагу 1" и "Перейти к шагу 4", соответственно.
Для оператора for используется следующий общий формат:
for (выражение1;выражение2;выражение3) оператор
Выполнение оператора осуществляется в соответствии со следующим алгоритмом:
В операторе for инструкции continue и break аналогичны действиям "Перейти к шагу 4" и "Перейти к шагу 6", соответственно.
Определяемые пользователем функции
В утилите bc предусмотрена возможность определения именованных функций, поддерживающих параметры, локальные переменные и рекурсию. Имя функции представляет собой одиночный символ нижнего регистра (от a до z). Для функции используется следующий общий формат:
define имя(список_параметров) { тело_функции }
Функции нельзя удалять или заменять. Попытка совершения этих действий приводит к возникновению ошибки. Функции могут вызывать другие функции, в том числе сами себя.
Функции могут принимать произвольное число параметров, которые могут быть или простыми переменными, или переменными типа "массив".
![]() | Параметры передаются по значению, то есть функции предоставляется частная копия всех параметров, действующая на протяжении выполнения функции. Следует отметить, что массивы также передаются по значению. Это отличается от соглашения о вызовах, принятого в языке C. |
Первым оператором в функции может быть оператор auto, обеспечивающий создание "локальных" переменных для этой функции. Для оператора auto используется следующий общий формат:
auto [variable|array]...
Локальные переменные используются вместо глобальных переменных с аналогичными именами на протяжении выполнения функции. Для локальных переменных также выполняется инициализация с присвоением значения 0 (см. приведенный ниже пример).
В функциях может содержаться оператор return. Оператор return обеспечивает завершение функции с игнорированием любых локальных переменных и параметров. Для этого оператора может использоваться любой из следующих двух форматов:
return
или
return [возвр_знач]
где возвр_знач – это константа или имя переменной. Если оператор return не задан или переменная возвр_знач опущена, то возвращается значение 0
.
В следующем примере показаны различные конструкции, используемые в функциях:
/* функция s(b[], n) возвращает сумму первых n элементов b[] */define s(b[],n) {auto t,i; /* следует отметить, что символы ';' используются только в стилистических целях и не являются обязательными. */if (n > 2048) {"Длина массива превышает допустимые пределы...\n"return 0;}for (i=0; i < n; i++) {t += b[i];}return t;}
Функция s() вводится оператором define, также определяющим типы параметров. При вызове любых функций важно использовать соответствующие типы и количество параметров. В противном случае могут возникнуть непредсказуемые ошибки.
![]() | Все параметры в утилите bc, в т.ч. массивы, передаются по значению. В этом заключается отличие от языка C, где массивы всегда передаются по ссылке. |
Оператор auto вводит локально видимые переменные t и i. Динамические переменные следует использовать для предотвращения нежелательных побочных эффектов от использования глобальных переменных.
Встроенные переменные и функции
На функционирование утилиты bc оказывают влияние несколько встроенных управляющих переменных. Предусмотрена возможность установки или запроса следующих переменных:
Имя | Функция | Диапазон | Значение по умолчанию |
---|---|---|---|
scale | Минимальная точность вычисления | 0..100 | 0 |
ibase | Основание системы счисления для ввода | 2..10000 числа | 10 |
obase | Основание системы счисления для вывода | 2..10000 числа | 10 |
Для утилиты bc предусмотрены следующие встроенные функции:
Функция | Возвращаемое значение |
---|---|
sqrt( выражение ) | Квадратный корень значения |
length( выражение ) | Количество значащих десятичных цифр в выражении |
scale( выражение ) | Количество десятичных цифр справа от десятичного маркера |
Библиотечные функции
Активация библиотеки bc выполняется при вызове утилиты bc с опцией -l или при указании файла интерпретации в командной строке. Библиотека обеспечивает установку точности (количества знаков после запятой), равной 20, которое можно переопределить путем назначения нового значения. В библиотеке определены следующие функции:
Синтаксис | Функция |
---|---|
a( выражение) | Арктангенс (в радианах) |
c( выражение ) | Косинус (в радианах) |
e( выражение ) | Экспоненциальная функция |
k( выражение1, выражение2 ) | Функция Бесселя целого порядка |
l( выражение ) | Натуральный логарифм |
s( выражение ) | Синус (в радианах) |
В синтаксисе утилиты bc встречается несколько неоднозначных моментов.
;
). Выражение может быть пустым, в таком случае оператор будет представлен только символом новой строки. В результате может возникнуть непредвиденное поведение, как в следующем примере, в котором оператор while никогда не завершается:
a=0while (a < 100)a++a
Несмотря на очевидность цели, символ новой строки в конце оператора while составляет тело цикла, поэтому a не увеличивается. Этот пример имеет следующий эквивалент на языке C:
a=0;while (a < 100);
Ниже приведены "правильные" варианты:
a=0while (a < 100) a++
или
while (++a < 100)
или
while (a < 100) {a++}
if (0) {quit}
Это равноценно следующему:
quit
Базовые подсистемы ЗОСРВ «Нейтрино», POSIX
Brian W. Kernighan and Dennis M. Ritchie, The C Programming Language, Prentice-Hall, 1978
Предыдущий раздел: Утилиты