note.nkmk.me

Pythonで2進数、8進数、16進数の数値・文字列を相互に変換

Posted: 2017-08-21 / Modified: 2021-01-07 / Tags: Python, 文字列処理

Pythonでは通常の10進数だけでなく2進数、8進数、16進数として数値や文字列を扱うことができる。相互に変換するのも簡単。

ここでは、以下の内容についてサンプルコードとともに説明する。

  • 整数を2進数、8進数、16進数で記述
  • 数値を2進数、8進数、16進数表記の文字列に変換
    • 組み込み関数bin(), oct(), hex()
    • 組み込み関数format(), 文字列メソッドstr.format(), f文字列
    • 負の整数を2の補数形式の文字列に変換
  • 2進数、8進数、16進数表記の文字列を数値に変換
    • 組み込み関数int()
  • 活用例
    • 2進数の文字列の演算
    • 2進数、8進数、16進数の相互変換

整数ではなく浮動小数点数float型を16進数の文字列に変換したい場合は以下の記事を参照。

そのほか、文字列strと数値int, floatの変換の基本については以下の記事を参照。

スポンサーリンク

整数を2進数、8進数、16進数で記述

プレフィックス0b, 0o, 0xをつけると、整数型intの数値をそれぞれ2進数、8進数、16進数で記述できる。print()での出力は10進数表記になる。

bin_num = 0b10
oct_num = 0o10
hex_num = 0x10

print(bin_num)
print(oct_num)
print(hex_num)
# 2
# 8
# 16

大文字0B, 0O, 0XでもOK。

Bin_num = 0B10
Oct_num = 0O10
Hex_num = 0X10

print(Bin_num)
print(Oct_num)
print(Hex_num)
# 2
# 8
# 16

プレフィックスがついていても、型としては整数型int

print(type(bin_num))
print(type(oct_num))
print(type(hex_num))
# <class 'int'>
# <class 'int'>
# <class 'int'>

print(type(Bin_num))
print(type(Oct_num))
print(type(Hex_num))
# <class 'int'>
# <class 'int'>
# <class 'int'>

整数型なので、そのまま普通に四則演算が可能。

result = 0b10 * 0o10 + 0x10
print(result)
# 32

Python3.6からは数値中にアンダースコア_を挿入できるようになった。アンダースコア_を繰り返すとエラーになるが、繰り返さなければ何個挿入してもよい。

アンダースコア_は数値に影響しないので桁数が多い場合などの区切りとして使える。例えば4桁ごとに_を入れると見やすい。

print(0b111111111111 == 0b1_1_1_1_1_1_1_1_1_1_1_1)
# True

bin_num = 0b1111_1111_1111
print(bin_num)
# 4095

数値を2進数、8進数、16進数表記の文字列に変換

数値を2進数、8進数、16進数表記の文字列に変換するには、

  • 組み込み関数bin(), oct(), hex()
  • 組み込み関数format(), 文字列メソッドstr.format(), f文字列

を使う。

負の値に対して2の補数形式で表現された文字列を取得する方法についても説明する。

組み込み関数bin(), oct(), hex()

組み込み関数bin(), oct(), hex()で、数値を2進数、8進数、16進数の文字列に変換できる。それぞれプレフィックス0b, 0o, 0xがついた文字列を返す。

i = 255

print(bin(i))
print(oct(i))
print(hex(i))
# 0b11111111
# 0o377
# 0xff

print(type(bin(i)))
print(type(oct(i)))
print(type(hex(i)))
# <class 'str'>
# <class 'str'>
# <class 'str'>

プレフィックスが不要な場合はスライス[2:]で後ろの文字列を取り出すか、次に説明するformat()を使う。

print(bin(i)[2:])
print(oct(i)[2:])
print(hex(i)[2:])
# 11111111
# 377
# ff

10進数の文字列に変換したい場合はstr()を使えばよい。

print(str(i))
# 255

print(type(str(i)))
# <class 'str'>

組み込み関数format(), 文字列メソッドstr.format(), f文字列

組み込み関数format()や文字列メソッドstr.format()およびf文字列でも、数値を2進数、8進数、16進数の文字列に変換できる。

format()の第二引数の書式化指定文字列にb, o, xを指定することで、それぞれ2進数、8進数、16進数の文字列に変換できる。

print(format(i, 'b'))
print(format(i, 'o'))
print(format(i, 'x'))
# 11111111
# 377
# ff

print(type(format(i, 'b')))
print(type(format(i, 'o')))
print(type(format(i, 'x')))
# <class 'str'>
# <class 'str'>
# <class 'str'>

プレフィックス0b, 0o, 0xがついた文字列を取得したい場合は書式化指定文字列に#をつける。

print(format(i, '#b'))
print(format(i, '#o'))
print(format(i, '#x'))
# 0b11111111
# 0o377
# 0xff

任意の桁数で0埋めすることも可能。プレフィックスをつけて0埋めする場合はプレフィックスの分の文字数(2文字)も考慮する必要があるので注意。

print(format(i, '08b'))
print(format(i, '08o'))
print(format(i, '08x'))
# 11111111
# 00000377
# 000000ff

print(format(i, '#010b'))
print(format(i, '#010o'))
print(format(i, '#010x'))
# 0b11111111
# 0o00000377
# 0x000000ff

文字列メソッドstr.format()でも同様に変換できる。

print('{:08b}'.format(i))
print('{:08o}'.format(i))
print('{:08x}'.format(i))
# 11111111
# 00000377
# 000000ff

書式化指定文字列の種類や書き方など、format(), str.format()についての詳細は以下の記事を参照。

Python3.6からはf文字列(f'xxx')を利用することもできる。

print(f'{i:08b}')
print(f'{i:08o}')
print(f'{i:08x}')
# 11111111
# 00000377
# 000000ff

負の整数を2の補数形式の文字列に変換

負の整数をbin()format()などで2進数や16進数の文字列に変換すると、絶対値にマイナス符号が付いた形になる。

x = -9

print(x)
print(bin(x))
# -9
# -0b1001

Pythonにおいても、負の整数のビット演算は2の補数表現で行われるため、2の補数形式で表現された文字列を取得したい場合は、4bitなら0b1111(=0xf)、8bitなら0xff、16bitなら0xffffのように、必要なビット桁数の最大値とのビット単位論理和&を取ればよい。

print(bin(x & 0xff))
print(format(x & 0xffff, 'x'))
# 0b11110111
# fff7

2進数、8進数、16進数表記の文字列を数値に変換

組み込み関数int()

2進数、8進数、16進数表記の文字列を数値に変換するには、組み込み関数int()を使う。

int(文字列, 基数)で基数をもとに2進数、8進数、16進数表記などの文字列strを数値intに変換できる。基数を省略した場合は10進数とみなされる。

print(int('10'))
print(int('10', 2))
print(int('10', 8))
print(int('10', 16))
# 10
# 2
# 8
# 16

print(type(int('10')))
print(type(int('10', 2)))
print(type(int('10', 8)))
print(type(int('10', 16)))
# <class 'int'>
# <class 'int'>
# <class 'int'>
# <class 'int'>

基数を0にすると、文字列のプレフィックス(0b, 0o, 0xまたは0B, 0O, 0X)をもとに変換される。

print(int('0b10', 0))
print(int('0o10', 0))
print(int('0x10', 0))
# 2
# 8
# 16

print(int('0B10', 0))
print(int('0O10', 0))
print(int('0X10', 0))
# 2
# 8
# 16

基数を0としたときプレフィックスがないと10進数として変換されるが、その場合は先頭(左側)が0埋めされているとエラーになるので注意。

print(int('10', 0))
# 10

# print(int('010', 0))
# ValueError: invalid literal for int() with base 0: '010'

そのほかの場合は0埋めされた文字列もそのまま変換可能。

print(int('010'))
# 10

print(int('00ff', 16))
print(int('0x00ff', 0))
# 255
# 255

指定した基数やプレフィックスで変換できない文字列の場合はエラーとなる。

# print(int('ff', 2))
# ValueError: invalid literal for int() with base 2: 'ff'

# print(int('0a10', 0))
# ValueError: invalid literal for int() with base 0: '0a10'

# print(int('0bff', 0))
# ValueError: invalid literal for int() with base 0: '0bff'

活用例

2進数の文字列の演算

例えば、プレフィックス0bが付いた2進数表記の文字列の演算を行う場合。

数値(整数型int)に変換して演算し、ふたたび文字列strに戻すといった操作が簡単に行える。

a = '0b1001'
b = '0b0011'

c = int(a, 0) + int(b, 0)

print(c)
print(bin(c))
# 12
# 0b1100

2進数、8進数、16進数の相互変換

2進数、8進数、16進数の文字列をそれぞれ相互に変換することも簡単。一度数値intに変換したあと任意の書式の文字列に変換すればよい。

0埋めやプレフィックスの有無などは書式化指定文字列で制御できる。

a_0b = '0b1110001010011'

print(format(int(a, 0), '#010x'))
# 0x00000009

print(format(int(a, 0), '#010o'))
# 0o00000011
スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事