Преобразовать десятичное значение в Base-4 в Баш
Я использовал довольно простой и по большей части прямой метод для преобразования чисел с базовыми 10 {1..256}
к основанию-4 или четвертичным числам. Я использовал простое деление $(($NUM/4))
чтобы получить основной результат, чтобы получить остатки $(($NUM%4))
а затем распечатывать остатки в обратном порядке, чтобы получить результат. Я использую следующее bash
скрипт для этого:
#!/bin/bash
NUM="$1"
main() {
local EXP1=$(($NUM/4))
local REM1=$(($NUM%4))
local EXP2=$(($EXP1/4))
local REM2=$(($EXP1%4))
local EXP3=$(($EXP2/4))
local REM3=$(($EXP2%4))
local EXP4=$(($EXP3/4))
local REM4=$(($EXP3%4))
echo "
$EXP1 remainder $REM1
$EXP2 remainder $REM2
$EXP3 remainder $REM3
$EXP4 remainder $REM4
Answer: $REM4$REM3$REM2$REM1
"
}
main
Этот скрипт отлично работает для чисел 0-255 или 1-256. Но за пределами этого (этих) диапазонов результаты становятся смешанными и часто повторяются или неточны. Это не такая большая проблема, так как я не собираюсь преобразовывать числа, превышающие 256 или меньше 0 (отрицательные числа [пока]).
Мой вопрос: "Есть ли более упрощенный метод для этого, возможно, с использованием expr
или же bc
?
2 ответа
Создать справочную таблицу, используя преимущества расширения скобок
$ echo {a..c}
a b c
$ echo {a..c}{r..s}
ar as br bs cr cs
$ echo {0..3}{0..3}
00 01 02 03 10 11 12 13 20 21 22 23 30 31 32 33
и так, для 0-255 в десятичном виде к основанию-4
$ base4=({0..3}{0..3}{0..3}{0..3})
$ echo "${base4[34]}"
0202
$ echo "${base4[255]}"
3333
База 4 преобразования в Баш
int2b4() {
local val out num ret=\\n;
for ((val=$1;val;val/=4)){
out=$((val%4))$out;
}
printf ${2+-v} $2 %s${ret[${2+1}]} $out
}
Вызывается только с 1 аргументом, это преобразует в базу 4 и печатает результат, за которым следует новая строка. Если присутствует второй аргумент, переменная с таким именем будет заполнена, без печати.
int2b4 135
2013
int2b4 12345678
233012011032
int2b4 5432 var
echo $var
1110320
Подробное объяснение:
Основная часть (можно написать):
out="" for (( val=$1 ; val > 0 ; val = val / 4 )) ;do out="$((val%4))$out" done
Мы можем легко понять цикл конверсии (я надеюсь)
local
обеспечиватьout val num
быть локальными пустыми переменными и инициализироваться локальноret='\n'
printf
линия использовать некоторые bashisms${2+-v}
пуст, если$2
пусто и представляет-v
если не.${ret[${2+1}]}
стать соответственно${ret[]}
(или же${ret[0]}
) а также${ret[1]}
Так что эта линия стала
printf "%s\n" $out
если нет второго аргумента ($2) и
printf -v var "%s" $out
если второй аргумент
var
(Обратите внимание, что новая строка не добавляется к заполненной переменной, но добавляется для печати терминала).
Преобразование обратно в десятичное:
Существует bashism, позволяющий вам вычислить произвольную базу под bash:
echo $[4#$var]
5432
echo $[4#1110320]
5432
В скрипте:
for integer in {1234..1248};do
int2b4 $integer quaternary;
backint=$[4#$quaternary];
echo $integer $quaternary $backint;
done
1234 103102 1234
1235 103103 1235
1236 103110 1236
1237 103111 1237
1238 103112 1238
1239 103113 1239
1240 103120 1240
1241 103121 1241
1242 103122 1242
1243 103123 1243
1244 103130 1244
1245 103131 1245
1246 103132 1246
1247 103133 1247
1248 103200 1248