expr
-
НАЗВАНИЕ
- expr — Вычисление выражения
- СИНТАКСИС
- ОПИСАНИЕ
- ОПЕРАНДЫ
- ОПЕРАТОРЫ
-
- + ~ !
- **
- * / %
- + -
- << >>
- < > <= >=
- == !=
- eq ne
- in ni
- &
- ^
- |
- &&
- ||
- x?y:z
- **
Имя
expr — Вычисление выраженияСинтаксис
expr arg ?arg arg ...?Описание
Объединяет arg (добавляя разделители пробелы между ними), вычисляет результат как выражение Tcl и возвращает значение. Допускаемые в выражениях Tcl операторы включают подмножество операторов языка C. Для операторов, общих для Tcl и C, Tcl применяет такое же значение и приоритет, как соответствующие операторы C. Выражения почти всегда дают числовые результаты (целые или вещественные числа). Например, выражениеexpr 8.2 + 6
вычисляется как 14,2. Выражения Tcl отличаются от выражений C способом задания операндов. Кроме того, выражения Tcl поддерживают нечисловые операнды и сравнение строк, а также некоторые дополнительные операторы, отсутствующие в C.
Операнды
Выражение Tcl состоит из комбинации операндов, операторов, скобок и запятых. Между операндами и операторами, а также скобками (или запятыми) можно использовать пробелы; они игнорируются инструкциями выражения. По возможности операнды интерпретируются как целые числа. Целые значения могут быть заданы в десятичном формате (обычный случай), в двоичном (если первые две буквы операнда — 0b), в восьмеричном (если первые две буквы операнда — 0o) или в шестнадцатеричном (если первые две буквы операнда — 0x). Для совместимости со старыми версиями Tcl восьмеричное целое значение также обозначается просто, когда первая буква операнда — 0, независимо от того, является ли вторая буква также o. Если операнд не имеет одного из вышеуказанных целочисленных форматов, то он обрабатывается как вещественное число, если это возможно. Вещественные числа могут быть заданы в нескольких распространённых форматах, использующих десятичные цифры, десятичную точку ., символы e или E, обозначающие научную запись, и знаки + или -. Например, все следующие являются допустимыми вещественными числами: 2.1, 3., 6e4, 7.91e+16. Также распознаются как вещественные значения строки Inf и NaN, используя любой регистр для каждой буквы. Если числовое толкование невозможно (обратите внимание, что все литеральные операнды, которые не являются числовыми или логическими, должны быть заключены в кавычки либо в фигурные, либо в двойные кавычки), то операнд оставляется как строка (и только ограниченное множество операторов может быть применено к нему).Операнды могут быть заданы любым из следующих способов:
- Как числовое значение, целое или вещественное.
- Как логическое значение, используя любой формат, понимаемый командой string is boolean.
- Как переменная Tcl, используя стандартную нотацию $. Значение переменной будет использовано в качестве операнда.
- Как строка, заключённая в двойные кавычки. Парсер выражений выполнит подстановки обратной косой черты, переменных и команд в информации между кавычками и использует полученное значение в качестве операнда
- Как строка, заключённая в фигурные скобки. Символы между открывающей и соответствующей закрывающей фигурной скобкой будут использоваться в качестве операнда без каких-либо подстановок.
- Как команда Tcl, заключённая в квадратные скобки. Команда будет выполнена, и её результат будет использован в качестве операнда.
- Как математическая функция, аргументы которой имеют любой из вышеперечисленных форм операндов, таких как sin($x). См. МАТЕМАТИЧЕСКИЕ ФУНКЦИИ ниже для обсуждения обработки математических функций.
Там, где происходят вышеупомянутые подстановки (например, внутри строк в кавычках), они выполняются инструкциями выражения. Однако парсер команд может уже выполнить один раунд подстановки до вызова процессора выражений. Как обсуждалось ниже, обычно лучше заключить выражения в фигурные скобки, чтобы предотвратить выполнение парсером команд подстановок на содержимом.
Для некоторых примеров простых выражений предположим, что переменная a имеет значение 3, а переменная b имеет значение 6. Тогда команда в левой части каждой из строк ниже даст значение в правой части строки:
expr 3.1 + $a 6.1
expr 2 + "$a.$b" 5.6
expr 4*[llength "6 2"] 8
expr {{word one} < "word $a"} 0 Операторы
Допустимые операторы (большинство из которых также доступны как команды в пространстве имён tcl::mathop; см. страницу справки mathop(n) для получения подробной информации) перечислены ниже, сгруппированные в порядке убывания приоритета:- - + ~ !
- Унарный минус, унарный плюс, побитовый НЕ, логическое НЕ. Ни один из этих операторов не может быть применён к строковым операндам, а побитовое НЕ может быть применено только к целым числам.
- **
- Возведение в степень. Допустимо для любых числовых операндов.
- * / %
- Умножение, деление, остаток от деления. Ни один из этих операторов не может быть применён к строковым операндам, а остаток от деления может быть применён только к целым числам. Остаток всегда имеет тот же знак, что и делитель, и абсолютное значение меньше абсолютного значения делителя.
При применении к целым числам операторы деления и остатка от деления могут рассматриваться как разбиение числовой прямой на последовательность равных смежных неперекрывающихся частей, где каждая часть имеет размер делителя; результат деления определяет, к какой части принадлежит делитель, а результат остатка от деления определяет, где в этой части находился делитель. Следствием этого является то, что результат «-57 / 10» всегда равен -6, а результат «-57 % 10» всегда равен 3.
- + -
- Сложение и вычитание. Допустимо для любых числовых операндов.
- << >>
- Сдвиг влево и вправо. Допустимо только для целочисленных операндов. Сдвиг вправо всегда распространяет знаковый бит.
- < > <= >=
- Логическое меньше, больше, меньше или равно, и больше или равно. Каждый оператор возвращает 1, если условие истинно, и 0 в противном случае. Эти операторы могут применяться к строковым, а также числовым операндам, в этом случае используется сравнение строк.
- == !=
- Логическое равно и не равно. Каждый оператор возвращает 0 или 1. Допустимо для всех типов операндов.
- eq ne
- Логическое строковое равенство и неравенство. Каждый оператор возвращает 0 или 1. Типы операндов интерпретируются только как строки.
- in ni
- Вхождение в список и отрицание вхождения в список. Каждый оператор возвращает 0 или 1 и обрабатывает свой первый аргумент как строку, а второй аргумент — как список Tcl. Оператор in указывает, является ли первый аргумент элементом второго списка аргументов; оператор ni инвертирует смысл результата.
- &
- Побитовое И. Допустимо только для целочисленных операндов.
- ^
- Побитовое исключающее ИЛИ. Допустимо только для целочисленных операндов.
- |
- Побитовое ИЛИ. Допустимо только для целочисленных операндов.
- &&
- Логическое И. Возвращает 1, если оба операнда отличны от нуля, 0 в противном случае. Допустимо только для логических и числовых (целых или вещественных) операндов.
- ||
- Логическое ИЛИ. Возвращает 0, если оба операнда равны нулю, 1 в противном случае. Допустимо только для логических и числовых (целых или вещественных) операндов.
- x?y:z
- Условная конструкция if-then-else, как в языке C. Если x вычисляется как не равное нулю, результат — значение y. В противном случае — значение z. Операнд x должен иметь логическое или числовое значение.
Для получения более подробной информации о результатах, производимых каждым оператором, обратитесь к руководству по языку C. Оператор возведения в степень повышает типы, как операторы умножения и деления, и возвращает результат, равный результату функции pow (после любых преобразований типов.) Все бинарные операторы, кроме возведения в степень, группируются слева направо в пределах одного уровня приоритета; возведение в степень группируется справа налево. Например, команда
expr {4*2 < 7} возвращает 0, в то время как
expr {2**3**2} возвращает 512.
Операторы &&, || и ?: имеют ленивую оценку, как и в языке C, что означает, что операнды не вычисляются, если они не нужны для определения результата. Например, в команде
expr {$v ? [a] : [b]} будет вычислено только одно из «[a]» или «[b]», в зависимости от значения $v. Обратите внимание, что это справедливо только если всё выражение заключено в фигурные скобки; в противном случае парсер Tcl вычислит и «[a]» и «[b]» до вызова команды expr.
Математические функции
Когда парсер выражений встречает математическую функцию, такую как sin($x), он заменяет её вызовом обычной функции Tcl в пространстве имён tcl::mathfunc. Обработка выражения, такого как:expr {sin($x+$y)} полностью аналогична обработке:
expr {[tcl::mathfunc::sin [expr {$x+$y}]]} которая в свою очередь аналогична обработке:
tcl::mathfunc::sin [expr {$x+$y}] Исполнитель будет искать tcl::mathfunc::sin, используя обычные правила для разрешения функций в пространствах имён. Запрос удовлетворит либо ::tcl::mathfunc::sin, либо [namespace current]::tcl::mathfunc::sin, и другие варианты тоже возможны (в зависимости от текущего параметра пути пространства имён).
Некоторые математические функции имеют несколько аргументов, разделённых запятыми, как в языке C. Например:
expr {hypot($x,$y)} превращается в
tcl::mathfunc::hypot $x $y
См. страницу руководства mathfunc(n) для математических функций, доступных по умолчанию.
Типы, переполнение и точность
Все внутренние вычисления с целыми числами выполняются с помощью библиотеки многоточечных целых чисел LibTomMath, чтобы все целочисленные вычисления выполнялись точно. Обратите внимание, что в версиях Tcl до 8.5 целочисленные вычисления выполнялись с одним из типов C long int или Tcl_WideInt, что приводило к неявной обрезке диапазона в тех вычислениях, где значения превышали диапазон этих типов. Любой код, который полагался на эти неявные обрезки, должен явно добавить вызовы функции int() или wide() к выражениям в тех местах, где такая обрезка требуется.Все внутренние вычисления с плавающей запятой выполняются с типом C double. При преобразовании строки в число с плавающей запятой обнаруживается переполнение показателя степени, что приводит к значению double Inf или -Inf, соответственно. Переполнение и подпотолочение с плавающей запятой обнаруживаются в той степени, в которой это поддерживается аппаратным обеспечением, что обычно достаточно надёжно.
Преобразование между внутренними представлениями для целых чисел, чисел с плавающей запятой и строковых операндов выполняется автоматически по мере необходимости. Для арифметических вычислений используются целые числа до тех пор, пока не будет введено какое-либо число с плавающей запятой, после чего используется плавающая запятая. Например,
expr {5 / 4} возвращает 1, а
expr {5 / 4.0}
expr {5 / ( [string length "abcd"] + 0.0 )} оба возвращают 1,25. Значения с плавающей запятой всегда возвращаются с «.» или «e», чтобы они не выглядели как целые числа. Например,
expr {20.0/5.0} возвращает 4.0, а не 4.
Строковые операции
Строковые значения могут использоваться в качестве операндов операторов сравнения, хотя интерпретатор выражений пытается выполнять сравнения как целые или вещественные числа, когда это возможно, т. е. когда все аргументы оператора допускают числовые интерпретации, за исключением операторов eq и ne. Если один из операндов сравнения — строка, а другой имеет числовое значение, генерируется каноническое строковое представление числового значения операнда для сравнения со строковым операндом. Каноническое строковое представление для целых чисел — десятичный формат строки. Каноническое строковое представление для чисел с плавающей запятой — то, которое создаётся спецификатором формата %g команды Tcl format. Например, командыexpr {"0x03" > "2"}
expr {"0y" > "0x12"} обе возвращают 1. Первое сравнение выполняется с использованием целочисленного сравнения, а второе — с использованием строкового сравнения. Из-за тенденции Tcl обрабатывать значения как числа всякий раз, когда это возможно, не рекомендуется использовать операторы, такие как ==, когда вы действительно хотите строковое сравнение, а значения операндов могут быть произвольными; в этих случаях лучше использовать операторы eq или ne, или команду string.
Учёт производительности
Заключите выражения в фигурные скобки для наилучшей скорости и наименьших требований к памяти. Это позволяет компилятору Tcl байткода генерировать лучший код.Как упоминалось выше, выражения подставляются дважды: один раз парсером Tcl, а второй — командой expr. Например, команды
set a 3
set b {$a + 2}
expr $b*4 возвращают 11, а не кратное 4. Это происходит потому, что парсер Tcl сначала подставит $a + 2 вместо переменной b, а затем команда expr вычислит выражение $a + 2*4.
Большинству выражений не требуется второй раунд подстановок. Либо они заключены в фигурные скобки, либо, если нет, их подстановки переменных и команд дают числа или строки, которые сами по себе не требуют подстановок. Однако, поскольку некоторым выражениям без фигурных скобок необходимы два раунда подстановок, компилятор байткода должен генерировать дополнительные инструкции для обработки этой ситуации. Самый дорогостоящий код требуется для выражений без фигурных скобок, содержащих подстановки команд. Эти выражения должны реализовываться путём генерации нового кода каждый раз при выполнении выражения. Когда выражение не заключено в фигурные скобки, чтобы разрешить подстановку функции или оператора, рассмотрите возможность использования команд, описанных на страницах руководства mathfunc(n) или mathop(n).
Примеры
Определите процедуру, вычисляющую «интересную» математическую функцию:proc tcl::mathfunc::calc {x y} {
expr { ($x**2 - $y**2) / exp($x**2 + $y**2) }
} Преобразуйте полярные координаты в декартовы:
# convert from ($radius,$angle)
set x [expr { $radius * cos($angle) }]
set y [expr { $radius * sin($angle) }] Преобразуйте декартовы координаты в полярные:
# convert from ($x,$y)
set radius [expr { hypot($y, $x) }]
set angle [expr { atan2($y, $x) }] Выведите сообщение, описывающее взаимоотношения двух строковых значений:
puts "a and b are [expr {$a eq $b ? {equal} : {different}}]" Установите переменную в значение, указывающее, определена ли переменная окружения и установлено ли она в истинное булево значение:
set isTrue [expr {
[info exists ::env(SOME_ENV_VAR)] &&
[string is true -strict $::env(SOME_ENV_VAR)]
}] Сгенерируйте случайное целое число в диапазоне 0..99 включительно:
set randNum [expr { int(100 * rand()) }] См. также
array, for, if, mathfunc, mathop, namespace, proc, string, Tcl, whileАвторские права
Авторские права (c) 1993 The Regents of the University of California.Авторские права (c) 1994-2000 Sun Microsystems Incorporated.
Авторские права (c) 2005 Kevin B. Kenny
Licensed under Tcl/Tk terms
https://www.tcl.tk/man/tcl/TclCmd/expr.htm
Licensed under Tcl/Tk terms
https://www.tcl.tk/man/tcl/TclCmd/expr.htm