在 bash 中将十进制转换为 Base-4

Convert decimal to Base-4 in bash

我一直在使用一种非常基本且大部分直接的方法将 10 进制数 {1..256} 转换为 4 进制数或四进制数。我一直在使用简单的除法 $(($NUM/4)) 来获得主要结果以获得余数 $(($NUM%4)) 然后反向打印余数以得出结果。我使用以下 bash 脚本来执行此操作:

#!/bin/bash

NUM=""

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(负数 [yet])的数字。

我的问题是:“是否有更简单的方法来执行此操作,可能使用 exprbc

利用 brace expansion

创建查找 table
$ 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 到 base-4

$ base4=({0..3}{0..3}{0..3}{0..3})
$ echo "${base4[34]}"
0202
$ echo "${base4[255]}"
3333

中的 Base 4 转换
int2b4() {
    local val out num ret=\n;
    for ((val=;val;val/=4)){
        out=$((val%4))$out;
    }
    printf ${2+-v}  %s${ret[${2+1}]} $out
}

仅使用 1 个参数调用,这将转换为 base 4 并打印结果,后跟 newline。如果存在第二个参数,将填充此名称的变量,不打印。

int2b4 135
2013
int2b4 12345678
233012011032

int2b4 5432 var
echo $var
1110320

详细解释:

  • 主要部分是(可以写成):

     out=""
     for (( val= ; val > 0 ; val = val / 4 )) ;do
         out="$((val%4))$out"
         done
    

    我们的转换循环很容易理解(我希望)

  • local确保out val num为局部空变量并在局部初始化ret='\n'

  • printf line use some bashisms

      如果</code>为空,则<li><code>${2+-v}为空,否则表示-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