Я часто использую bc
утилиту для преобразования шестнадцатеричного числа в десятичное и наоборот. Тем не менее, это всегда бит проб и ошибок, как ibase
и obase
должно быть настроено. Например, здесь я хочу преобразовать шестнадцатеричное значение C0 в десятичное:
$ echo "ibase=F;obase=A;C0" | bc
180
$ echo "ibase=F;obase=10;C0" | bc
C0
$ echo "ibase=16;obase=A;C0" | bc
192
В чем тут логика? obase
( A
в моем третьем примере) должно быть в той же базе, что и преобразованное значение ( C0
в моих примерах), и ibase
( 16
в моем третьем примере) должно быть в базе, в которую я преобразую?
Ответы:
То, что вы на самом деле хотите сказать, это:
для шестнадцатеричной системы счисления и:
для десятичного в шестнадцатеричное.
Вам не нужно указывать и то,
ibase
и другоеobase
для преобразования с десятичными числами, так как эти настройки по умолчанию равны 10.Вы действительно должны дать как для таких преобразований , как двоичные-на-шестнадцатеричный. В этом случае мне проще всего разобраться, если вы дадите
obase
сначала:Если
ibase
вместо этого вы дадите сначала, это изменит интерпретацию следующегоobase
параметра, поэтому команда должна быть:Это связано с тем, что в этом порядке
obase
значение интерпретируется как двоичное число, поэтому необходимо получить 10000 hex = 16, чтобы получить вывод в шестнадцатеричном виде. Это неуклюжеТеперь давайте выясним, почему ваши три примера ведут себя так, как они.
echo "ibase=F;obase=A;C0" | bc
180
Это устанавливает для входной базы значение 15, а для выходной базы - 10, поскольку однозначное значение интерпретируется в шестнадцатеричном виде, в соответствии с POSIX . Это попросит
bc
вас сказать, что такое C0₁₅ в базе A₁₅ = 10, и он правильно отвечает на 180₁₀, хотя это, конечно, не тот вопрос, который вы хотели задать.echo "ibase=F;obase=10;C0" | bc
C0
Это нулевое преобразование в базе 15.
Зачем? Во-первых, потому что одна
F
цифра интерпретируется в шестнадцатеричном виде, как я указывал в предыдущем примере. Но теперь, когда вы установили его на основание 15, следующий выходной базовый параметр интерпретируется таким образом, и 10₁₅ = 15, так что у вас есть нулевое преобразование из C0₁₅ в C0₁₅.Правильно, вывод не в шестнадцатеричном виде, как вы предполагали, он в базе 15!
Вы можете доказать это себе, пытаясь преобразовать
F0
вместоC0
. ПосколькуF
в базе 15 нет цифры,bc
она фиксируетсяE0
и выдаетсяE0
в качестве выходного значения.echo "ibase=16; obase=A; C0"
192
Это единственный из ваших трех примеров, который, вероятно, имеет какое-либо практическое применение.
Он сначала меняет базу ввода на hex , так что вам больше не нужно копаться в спецификации POSIX, чтобы понять, почему
A
в данном случае интерпретируется как hex, 10. Единственная проблема заключается в том, что излишне устанавливать выходную базу равной A₁₆ = 10, поскольку это ее значение по умолчанию.источник
Установка
ibase
означает, что вам нужно установитьobase
в той же базе. Объяснение ваших примеров покажет это:Вы
bc
должны учитывать входные числа, представленные в базе 15 с «ibase = F». «obase = A» устанавливает выходные значения в базу 10, которая используется по умолчанию.bc
читает C0 как базовое число 15: C = 12. 12 * 15 = 180.В этом случае вы устанавливаете вход для базы 15, а выход для 10 - для базы 15, поэтому выходной базой является 15. Вход C0 в базе 15 - это выход C0 в базе 15.
Установите вход на базу 16, выход на базу 10 (A в базе 16 - 10 в базе 10).
C0, преобразованный в основание 10: 12 * 16 = 192
Мое личное правило - сначала установить obase, чтобы я мог использовать базу 10. Затем установите ibase, также используя базу 10.
Обратите внимание, что
bc
имеет ироническое исключение:ibase=A
иobase=A
всегда устанавливает ввод и вывод в базу 10. Наbc
странице руководства :Это поведение закреплено в спецификации
bc
: Из спецификации OpenGroup 2004 годаbc
:Вот почему
ibase=F
настройка изменила вашу базу ввода на базу 15, и поэтому я рекомендовал всегда устанавливать базу, используя базу 10. Избегайте путаницы.источник
Все числа интерпретируются GNU bc как текущая база ввода, которая действует для оператора, в котором появляется число. Когда вы используете цифру вне текущего ввода, интерпретируйте их как самую высокую цифру, доступную в базе (9 в десятичной дроби), когда часть из нескольких цифр или в качестве их нормальных значений при использовании в качестве однозначного числа (
A
== 10 в десятичном виде).Из руководства GNU BC :
Однако вы должны знать, что стандарт POSIX определяет это поведение только для присваиваний
ibase
иobase
, а не в каком-либо другом контексте.Из спецификации SUS на bc :
Ключевым фактором, который вам не хватает, является то, что F на самом деле не шестнадцать, а на самом деле пятнадцать, поэтому, когда вы устанавливаете ibase = F, вы устанавливаете базу ввода на пятнадцать.
Поэтому, чтобы переносимый установить IBase в шестнадцатеричный из неизвестного государства, то , следовательно , необходимо использовать два заявление:
ibase=A; ibase=16
. Тем не менее, в начале программы вы можете положиться на десятичность и просто использоватьibase=16
.источник
ibase=A; ibase=16
.Всегда рекомендуется устанавливать
ibase
иobase
использовать однозначное число, а не число, такое как16
, согласноbc
странице руководства ,Это означает, что
A,B,...,F
всегда имеют значения10,11,...,15
соответственно, независимо от значенияibase
. Вы также можете использовать,F+1
чтобы указать номер16
. Например, вам лучше написатьвместо записи
echo "ibase=16; obase=A; C0" | bc
указать, что база ввода есть,16
а база вывода есть10
. Или, например, если вы хотите, чтобыibase
иobase
16, и вам лучше использоватьвместо того, чтобы использовать
ibase=16; obase=10
. Точно так же, если вы собираетесь ввести свои числа в базу 14 и вывести их в базу 16, используйтеХотя формы для ванны имеют одинаковые результаты, первая менее подвержена ошибкам, а вторая может привести к большей путанице и ошибкам.
Разница между этими двумя формами становится особенно очевидной, когда вы находитесь в среде выполнения
bc
или собираетесь записать свои вычисления в файл, а затем передать этот файлbc
в качестве аргумента. В таких ситуациях вам может потребоваться изменить значенияibase
иobase
несколько раз, и использование последней формы может привести к серьезной путанице и ошибкам. (испытать это)источник