bc и его параметры ibase / obase: - PullRequest
3 голосов
/ 27 марта 2012

Я наткнулся на любопытную ошибку, я думаю:

Я попытался прочитать «512» как число для базы 6 и вывести его как базу 16:

echo "ibase=6;obase=16;512" | bc
161

Как видите, выходное значение равно 161, но оно должно быть bc (sic!). Я пробовал с базой 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 ]

25 голосов
/ 27 марта 2012

Не ошибка.

Как только 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
3 голосов
/ 27 марта 2012

См. 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#SEC9

Входные числа могут содержать символы 0-9 и A-F. (Примечание: они должны быть прописными. Буквы в нижнем регистре являются именами переменных.) Однозначные числа всегда имеют значение цифры независимо от значения 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
0 голосов
/ 12 мая 2018

Немного измените код (двумя способами), и появятся ожидаемые результаты:

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;

выполнить в песочнице bash

результаты для обоих способов:

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
...