bc и его опции ibase/obase:
Я наткнулся на любопытную ошибку, я думаю:
Я попытался прочитать "512" как число для базы 6 и вывести его как базу 16:
echo "ibase=6;obase=16;512" | bc
161
Как видите, на выходе 161, но оно должно быть bc
(Так!). Я попробовал с базой 10:
echo "ibase=6;obase=10;512" | bc
512
Значение не изменяется. Любопытно! По умолчанию obase - 10. Если я его опущу:
echo "ibase=6;512" | bc
188
Ну, это кажется правильным. В два этапа это работает:
echo "obase=16;"$(echo "ibase=6;512" | bc) | bc
BC
Поэтому я сделал скрипт для разных баз, но он меня озадачивает:
for ib in {6,8,10,16}; do echo $ib; for ob in {10,16}; do echo -en $ib $ob" \t => " ; echo "ibase=$ib;obase=$ob;333" | bc ; done; done;
6
6 10 => 333
6 16 => 108
8
8 10 => 333
8 16 => 119
10
10 10 => 333
10 16 => 14D
16
16 10 => 333
16 16 => 01 15 05
Должен ли я подать отчет об ошибке или я пропущу очевидное? Я не могу поверить, что такой основной инструмент сломан.
3 ответа
Не ошибка
Как только ibase=6
интерпретируется, цифры читаются в базе 6. Так ibase=6;obase=16
делает значение obase равным 16 основам6, что недопустимо и интерпретируется как 11десятичное число.
Со страницы руководства:
Для многозначных чисел bc изменяет все входные цифры, большие или равные ibase, на значение ibase-1.
Таким образом, 16 интерпретируется как 15основание 6, которое является 11десятичным. И преобразование правильное.
Задавать obase
до ibase
, или не забудьте указать свой obase в базе ibase
,
$ echo "obase=16;ibase=6;512" | bc
BC
Смотрите http://docstore.mik.ua/orelly/unix/upt/ch49_03.htm
Когда вы установите ibase
или же obase
это выражается с текущей базой ibase
, Так установить obase
прежде чем установить ibase
если вы хотите выразить obase
в десятичном.
Смотрите также http://www.gnu.org/software/bc/manual/html_mono/bc.html
Входные числа могут содержать символы 0-9 и AF. (Примечание: они должны быть прописными. Буквы в нижнем регистре являются именами переменных.) Однозначные числа всегда имеют значение цифры независимо от значения ibase. (т. е. A = 10.) Для многозначных чисел bc изменяет все входные цифры, большие или равные ibase, на значение ibase-1. Это делает число FFF всегда самым большим трехзначным числом входной базы.
Таким образом, для obase=16
в ibase=6
, 6
становится 5
, и это эквивалентно выходной базе десятичной 6 * 1 + 1 * 5 == 11
, таким образом:
$ echo "obase=11;ibase=6;512" | bc
161
Немного измените код (двумя способами), и ваши ожидаемые результаты появятся:
for ib in {6,8,10,16}; do
echo $ib; for ob in {10,16}; do
echo -en $ib $ob" \t => " ;
ob=`echo "obase=$ib;$ob" | bc`
echo "ibase=$ib;obase=$ob;333" | bc ;
done;
done;
for ib in {6,8,10,16}; do
echo $ib; for ob in {10,16}; do
echo -en $ib $ob" \t => " ;
echo "obase=$ob;ibase=$ib;333" | bc ;
done;
done;
Результаты для обоих способов:
6
6 10 => 129
6 16 => 81
8
8 10 => 219
8 16 => DB
10
10 10 => 333
10 16 => 14D
16
16 10 => 819
16 16 => 333