シェルスクリプトで数値をN進数に変換する方法

2023-03-27Bash

はじめに

競技プログラミングで問題を解いているときによく出題される問題として、 数値を N 進数表記に変換する というものがあります。
プログラミング言語だとかんたんなのですが、シェルスクリプトでやろうとすると普段やらないためやり方が分からずハマってしまいます。

変換方法を紹介します。

検証環境

$ uname -moi
x86_64 x86_64 GNU/Linux

$ head -n 2 /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"

$ bash -version | head -n 1
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)

Bash 組み込みの算術演算を利用する

これが最もかんたんです。

10101 を変換してみます。

# 10101 を変換 ( 2進数→10進数 )
$ echo $((2#10101))
21

# 10101 を変換 ( 8進数→10進数 )
$ echo $((8#10101))
4161

# 10101 を変換 ( 16進数→10進数 )
$ echo $((16#10101))
65793

ポイントは数値の前に N# のように基数を指定する点です。

ただし、N進数から10進数への変換しかできません。

bc コマンドを利用する

bc コマンドに標準入力で計算式を渡してやります。
その際に、インプット時の基数、アウトプット時の基数を指定してやります。
(obase、ibaseの記述順序に注意!)

# 10101 を変換 ( 2進数→10進数 )
$ bc <<<"obase=10; ibase=2; 10101"
21

# 10101 を変換 ( 8進数→10進数 )
$ bc <<<"obase=10; ibase=8; 10101"
4161

# 10101 を変換 ( 16進数→10進数 )
$ bc <<<"obase=10; ibase=16; 10101"
65793

# 21 を変換 ( 10進数→2進数 )
$ bc <<<"obase=2; ibase=10; 21"
10101

# 4161 を変換 ( 10進数→8進数 )
$ bc <<<"obase=8; ibase=10; 4161"
10101

# 65793 を変換 ( 10進数→16進数 )
$ bc <<<"obase=16; ibase=10; 65793"
10101

Bashの「算術式」機能を利用する

Bashでは、 $((...)) で括られた内側に計算式を記述する事ができます。(「算術式」)

特殊な記法を利用することで、 N進数から10進数 への変換が可能です。

残念ですが逆はできません。

# 10101 を変換 ( 2進数→10進数 )
$ echo $((2#10101))
21

# 10101 を変換 ( 8進数→10進数 )
$ echo $((8#10101))
4161

# 10101 を変換 ( 16進数→10進数 )
$ echo $((16#10101))
65793

ひとこと

どんなときでも bc を使っておいたら間違いなさそうです。

2023-03-27Bash