Листинг 3.7.Тестирование сценария calc
$ calc 150 / 3.5
42.85
$ calc
Calc −a simple calculator. Enter 'help’ for help, 'quit’ to quit.
calc> help
··In addition to standard math functions, calc also supports:
··a % b···· remainder of a/b
··a ^ b···· exponential: a raised to the b power
··s(x)······sine of x, x in radians
··c(x)······cosine of x, x in radians
··a(x)······arctangent of x, in radians
··l(x)······natural log of x
··e(x)······exponential log of raising e to the x
··j(n,x)····Bessel function of integer order n of x
··scale N·· show N fractional digits (default = 2)
calc> 54354 ^ 3
160581137553864
calc> quit
$
ВНИМАНИЕ
Вычисления с вещественными числами, даже простые для человека, могут быть сложными для компьютеров. К сожалению, команда bc иногда реагирует на такие сложности самым неожиданным образом. Например, запустите bc и введите scale=0 и затем 7 % 3. А теперь попробуйте вычислить то же выражение с scale=4. В результате вы получите.0001, что, очевидно, является ошибкой.
Усовершенствование сценария
Все, что можно сделать в bc, можно сделать и в этом сценарии, с той лишь разницей, что calc не имеет памяти команд или состояний. Попробуйте добавить больше математических функций в справочное сообщение. Например, переменные obase и ibase позволяют определить основание системы счисления для вывода и ввода, однако из-за того, что сценарий не имеет памяти команд, вам придется изменить scriptbc (сценарий № 9 в главе 1) или научиться вводить настройки и выражения в одной строке.
№ 24. Преобразование температур
Сценарий в листинге 3.8 — первый в книге, выполняющий сложные математические вычисления, — может преобразовывать значение температуры в градусы Фаренгейта, Цельсия и Кельвина. В нем используется тот же трюк передачи выражений для вычисления калькулятору bc, что и в сценарии № 9, в главе 1.
Листинг 3.8.Сценарий convertatemp
··#!/bin/bash
··# convertatemp — сценарий преобразования температуры, позволяющий вводить
··#·· температуру в градусах Фаренгейта, Цельсия или Кельвина и получать
··#·· эквивалентную температуру в двух других шкалах
··if [$# −eq 0]; then
····cat << EOF >&2
··Usage: $0 temperature[F|C|K]
··where the suffix:
····F······indicates input is in Fahrenheit (default)
····C······indicates input is in Celsius
····K······indicates input is in Kelvin
··EOF
····exit 1
··fi
··unit="$(echo $1|sed −e 's/[-[: digit: ]]*//g' | tr '[: lower: ]' '[: upper: ]')"
··temp="$(echo $1|sed −e 's/[^-[: digit: ]]*//g')"
··case ${unit:=F}
··in
··F) # Градусы Фаренгейта в градусы Цельсия: Tc = (F — 32) / 1.8
····farn="$temp"
····cels="$(echo "scale=2;($farn — 32) / 1.8" | bc)"
····kelv="$(echo "scale=2;$cels + 273.15" | bc)"
····;;
··C) # Градусы Цельсия в градусы Фаренгейта: Tf = (9/5)*Tc+32
····cels=$temp
····kelv="$(echo "scale=2;$cels + 273.15" | bc)"
····farn="$(echo "scale=2;(1.8 * $cels) + 32" | bc)"
····;;
··K) # Градусы Цельсия = Kelvin — 273.15,
······#·· затем использовать формулу градусы Цельсия — > градусы Фаренгейта
····kelv=$temp
····cels="$(echo "scale=2; $kelv — 273.15" | bc)"
····farn="$(echo "scale=2; (1.8 * $cels) + 32" | bc)"
····;;
····*)
····echo "Given temperature unit is not supported"
····exit 1
··esac
··echo "Fahrenheit = $farn"
··echo "Celsius = $cels"
··echo "Kelvin = $kelv"
··exit 0
Большая часть сценария, вероятно, ясна, но давайте внимательнее рассмотрим математические вычисления и регулярные выражения, выполняющие основную работу. Многие плохо воспринимают математические формулы в таком виде, поэтому ниже приводится формула преобразования температуры по Фаренгейту в температуру по Цельсию:
Преобразованную в последовательность для передачи калькулятору bc и вычисления, эту формулу можно видеть в строке
. Обратное преобразование из градусов Цельсия в градусы Фаренгейта реализовано в строке
. Этот сценарий также переводит температуру из градусов Цельсия в градусы Кельвина
. Он наглядно демонстрирует одну важную причину использовать мнемонические имена для переменных: код становится проще для чтения и отладки.
Читать дальше