Я правильно сравниваю шестнадцатеричные значения в tcl? - PullRequest
0 голосов
/ 25 марта 2019

Я делаю простое шестнадцатеричное сравнение в операторе if.

0x7843E0 больше 0x780000, но код ниже ничего не выводит.

if {"780000" <= "7843E0"} {
    puts "True!"
}
>>

Пропуск трейлинг 0 работает нормально, однако.

if {"780000" <= "7843E"} {
    puts "True!"
}
>>> True!

Должно быть что-то не так с конечным 0, но я не понимаю, что это такое. Есть идеи?

1 Ответ

2 голосов
/ 25 марта 2019

У вас проблемы с тем, как команда expr анализирует числа. (Остальная часть Tcl более спокойно относится к этому.) Проблема в том, что:

  • "780000" интерпретируется как десятичное целое число .
  • "7843E0" интерпретируется как число с плавающей запятой двойной точности . (Сравните с 1.2e10; анализатор чисел считает, что он соответствует шаблону того же типа.)
  • "780000" интерпретируется как десятичное целое число .
  • "7843E" интерпретируется как нечисловая строка (запасной вариант, поскольку числовая интерпретация недопустима).

Оператор <= с радостью сравнивает два числа, если они оба числа, или две строки, если хотя бы один из параметров для него не числовой. (Да, это иногда приводит к странной семантике.) Более того, команда expr стремится интерпретировать значения как числа, если это возможно, но все же имеет синтаксические правила Tcl для того, что на самом деле является числовым, и какой тип числового вещи есть. Когда вы не придерживаетесь правил, это становится немного странным.

Чтобы получить значение, интерпретируемое как шестнадцатеричное, вы должны либо префиксить его строковое представление с помощью 0x (например, 0x7843E0) или , либо принудительно заставить вещи с помощью такой команды, как scan с %x:

scan "780000" %x a
scan "7843E0" %x b
if {$a <= $b} {
    puts "True"
}

Форсирование интерпретаций с помощью scan считается одним из лучших способов справиться с этим, поскольку он записывает только канонические значения в переменные. (Если вы хотите обрабатывать восьмеричные числа или хотите, чтобы они всегда были десятичными, вы бы использовали %o и %d соответственно; %f для чисел с плавающей запятой.)

Наконец, если вы действительно сравниваете значения как строки с обычными ASCII-подобными правилами, посмотрите на string compare вместо непосредственного использования <=.

if {[string compare $input1 $input2] <= 0} {
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...