Python

【Python】16進数の変換方法【16進数文字列変換:16進数に変換:hex:int】

当サイトでは記事内に広告を含みます
技術ブログ特化メルマガはこちら

Pythonでプログラミングをしていると、色の表現やメモリアドレス、バイトデータの処理など、16進数を扱う場面が数多くあります。16進数は0から9までの数字とAからFまでのアルファベットを使って表現され、コンピュータの世界では非常に重要な表記法です。

しかし、「10進数を16進数に変換するにはどうすればいいのか」「16進数の文字列を数値として扱うには」「変換時のエラーにどう対処すればいいのか」など、初心者の方には疑問点も多いのではないでしょうか。

この記事では、Pythonにおける16進数の変換方法について、hex()関数とint()関数を中心に、基本的な使い方から実践的な応用例まで詳しく解説していきます。色コードの処理やバイナリデータの扱いなど、実用的なコード例も豊富に掲載していますので、実際に手を動かしながら理解を深めていただけるでしょう。

Pythonでの16進数変換の基本

それではまず、Pythonにおける16進数変換の基本について解説していきます。

hex()関数による10進数から16進数への変換

Pythonで10進数を16進数に変換するには、

組み込み関数であるhex()を使用します

。この関数は整数を引数として受け取り、16進数表記の文字列を返してくれるのです。

基本的な使い方を見てみましょう。

# 10進数の255を16進数に変換
result = hex(255)
print(result)  # 出力: 0xff

hex()関数は、戻り値として「0x」というプレフィックスが付いた文字列を返します。この「0x」は、その後に続く数字が16進数であることを示す接頭辞です。

正の数だけでなく、負の数や0も変換可能です。16進数のアルファベット部分は小文字で出力されます。

print(hex(0))     # 出力: 0x0
print(hex(255))   # 出力: 0xff
print(hex(4095))  # 出力: 0xfff
print(hex(-255))  # 出力: -0xff

int()関数による16進数から10進数への変換

逆に、16進数から10進数への変換にはint()関数を使用します。int()関数は第1引数に変換したい文字列、第2引数に基数(何進数か)を指定することで、様々な進数から10進数への変換が可能です。

16進数から10進数への変換では、第2引数に16を指定するのです。

# 16進数の文字列を10進数に変換
result = int('ff', 16)
print(result)  # 出力: 255

# 0xプレフィックス付きでも変換可能
result2 = int('0xff', 16)
print(result2)  # 出力: 255

# 大文字でもOK
result3 = int('FF', 16)
print(result3)  # 出力: 255

int()関数は、「0x」プレフィックスの有無や、アルファベットの大文字小文字に関わらず正しく変換してくれます。これにより、hex()関数の出力をそのままint()関数に渡すことも可能でしょう。

変換結果の特徴と注意点

10進数と16進数の変換を行う際には、いくつか押さえておくべき特徴と注意点があります。

まず、hex()関数の戻り値は文字列型(str)である点に注意が必要です。数値として計算に使用する場合は、再度int()で変換する必要があります。

関数 入力 出力 出力の型
hex() 整数(int) ‘0x…’形式の文字列 str
int(x, 16) 16進数文字列(str) 10進数の整数 int

また、hex()関数は整数のみを受け付けます。浮動小数点数を渡すとエラーになるため、事前にint()で整数化するか、float.hex()メソッドを使用する必要があるでしょう。

# 整数のみ受け付ける
# result = hex(10.5)  # TypeError発生

# 整数化してから変換
result = hex(int(10.5))
print(result)  # 出力: 0xa

# 浮動小数点数専用のメソッド
result_float = (10.5).hex()
print(result_float)  # 出力: 0x1.5000000000000p+3

10進数から16進数への変換方法の詳細

続いては、10進数から16進数への変換について、より詳しく確認していきます。

hex()関数の実用的な使い方

hex()関数は、Pythonの組み込み関数の中でも特にシンプルな使い方ができます。引数は1つだけで、変換したい整数を渡すだけです。

実際の使用例をいくつか見てみましょう。

# 基本的な変換
num = 255
hexadecimal = hex(num)
print(f"{num}の16進数表現: {hexadecimal}")  # 出力: 255の16進数表現: 0xff

# RGB色コードの生成
red = 255
green = 128
blue = 64
color_code = f"#{hex(red)[2:].zfill(2)}{hex(green)[2:].zfill(2)}{hex(blue)[2:].zfill(2)}"
print(f"色コード: {color_code}")  # 出力: 色コード: #ff8040

# ループで複数の数値を変換
for i in [10, 15, 16, 255, 256]:
    print(f"{i:3d} → {hex(i)}")
# 出力:
#  10 → 0xa
#  15 → 0xf
#  16 → 0x10
# 255 → 0xff
# 256 → 0x100

hex()関数は非常に高速で、大きな数値でも瞬時に変換が完了します。メモリアドレスの表示などでもよく使用されるでしょう。

format()関数を使った変換方法

hex()関数以外にも、format()関数やf文字列を使って16進数に変換することができます。この方法は、出力形式をより柔軟にカスタマイズしたい場合に便利です。

format()関数では、フォーマット指定子として’x'(小文字)または’X'(大文字)を使用します。

num = 255

# format()関数を使用(小文字)
hex1 = format(num, 'x')
print(hex1)  # 出力: ff (0xプレフィックスなし)

# 大文字で出力
hex2 = format(num, 'X')
print(hex2)  # 出力: FF

# f文字列を使用
hex3 = f"{num:x}"
print(hex3)  # 出力: ff

# ゼロ埋めを指定(8桁)
hex4 = format(num, '08x')
print(hex4)  # 出力: 000000ff

# 0xプレフィックス付き
hex5 = format(num, '#x')
print(hex5)  # 出力: 0xff

format()関数の利点は、

デフォルトで0xプレフィックスが付かない点と、大文字小文字や桁数を指定できる点

です。特に、固定長の16進数表現が必要な場合や、色コードを生成する場合に重宝するでしょう。

フォーマット 説明 例(255の場合)
😡 16進数表記(小文字) ff
:X 16進数表記(大文字) FF
:08x 8桁ゼロ埋め16進数 000000ff
:#x 0xプレフィックス付き 0xff

0xプレフィックスを除去する方法

hex()関数で変換した結果から「0x」プレフィックスを除去したい場合があります。これにはいくつかの方法があるのです。

最もシンプルな方法は、文字列のスライス機能を使って最初の2文字を除去することでしょう。

num = 255

# hex()で変換
hex_with_prefix = hex(num)
print(hex_with_prefix)  # 出力: 0xff

# スライスで0xを除去
hex_without_prefix = hex_with_prefix[2:]
print(hex_without_prefix)  # 出力: ff

# replace()メソッドを使う方法
hex_replaced = hex_with_prefix.replace('0x', '')
print(hex_replaced)  # 出力: ff

# format()を使えば最初からプレフィックスなし
hex_format = format(num, 'x')
print(hex_format)  # 出力: ff

# 大文字で取得
hex_upper = format(num, 'X')
print(hex_upper)  # 出力: FF

負の数の場合はスライスの位置に注意が必要です。マイナス記号を保持しながらプレフィックスだけを除去するには、replace()メソッドを使うのが安全でしょう。

negative = -255
hex_neg = hex(negative)  # -0xff

# replace()を使うのが安全
result = hex_neg.replace('0x', '')
print(result)  # 出力: -ff

# または条件分岐
if hex_neg.startswith('-'):
    result = '-' + hex_neg[3:]
else:
    result = hex_neg[2:]
print(result)  # 出力: -ff

16進数から10進数への変換方法の詳細

続いては、16進数から10進数への変換について詳しく見ていきます。

int()関数の基本的な使い方

int()関数で16進数を10進数に変換する際は、

第1引数に16進数の文字列、第2引数に基数16を指定

します。この基数指定により、文字列が何進数で表現されているかをPythonに伝えるのです。

基本的な使用例を確認しましょう。

# 16進数文字列を10進数に変換
hex1 = 'ff'
decimal1 = int(hex1, 16)
print(decimal1)  # 出力: 255

# 0xプレフィックス付きでもOK
hex2 = '0xff'
decimal2 = int(hex2, 16)
print(decimal2)  # 出力: 255

# 大文字でも変換可能
hex3 = 'FF'
decimal3 = int(hex3, 16)
print(decimal3)  # 出力: 255

# より大きな数値
hex4 = 'ffff'
decimal4 = int(hex4, 16)
print(decimal4)  # 出力: 65535

int()関数は、文字列に含まれる空白を無視してくれます。ただし、0-9とA-F(a-f)以外の文字が含まれているとエラーになります。

# 空白があってもOK
result1 = int('  ff  ', 16)
print(result1)  # 出力: 255

# アンダースコア区切り(Python 3.6以降)
result2 = int('ff_ff', 16)
print(result2)  # 出力: 65535

# 負の数
result3 = int('-ff', 16)
print(result3)  # 出力: -255

色コードや文字列データの変換

実際のプログラムでは、HTML/CSSの色コードやバイナリデータなど、様々な形式の16進数文字列を変換する必要があることが多いでしょう。そのような場合の処理方法を見ていきます。

# HTML色コードから RGB値を取得
color_code = "#ff8040"

# #を除去して変換
hex_value = color_code[1:]  # ff8040
decimal_value = int(hex_value, 16)
print(f"10進数: {decimal_value}")  # 出力: 10進数: 16744512

# RGB成分に分解
red = int(hex_value[0:2], 16)
green = int(hex_value[2:4], 16)
blue = int(hex_value[4:6], 16)
print(f"R:{red}, G:{green}, B:{blue}")  # 出力: R:255, G:128, B:64

# 複数の色コードを一括変換
color_codes = ["#ff0000", "#00ff00", "#0000ff"]
rgb_values = []
for code in color_codes:
    hex_val = code[1:]
    r = int(hex_val[0:2], 16)
    g = int(hex_val[2:4], 16)
    b = int(hex_val[4:6], 16)
    rgb_values.append((r, g, b))

print(rgb_values)
# 出力: [(255, 0, 0), (0, 255, 0), (0, 0, 255)]

また、hex()関数の出力をそのまま変換することもできます。

# hex()で変換した結果を再度10進数に戻す
original = 255
hexadecimal = hex(original)
print(f"16進数: {hexadecimal}")  # 出力: 16進数: 0xff

# そのまま変換可能
restored = int(hexadecimal, 16)
print(f"復元: {restored}")  # 出力: 復元: 255

# 確認
print(original == restored)  # 出力: True

エラー処理と例外対応

16進数から10進数への変換では、不正な文字列が渡されるとValueErrorが発生します。実用的なプログラムでは、適切なエラー処理を実装することが重要でしょう。

def safe_hex_to_decimal(hex_str):
    """
    安全に16進数を10進数に変換する関数
    """
    try:
        # 前後の空白を除去
        hex_str = hex_str.strip()
        
        # #記号を除去(色コード対応)
        if hex_str.startswith('#'):
            hex_str = hex_str[1:]
        
        # 変換実行
        result = int(hex_str, 16)
        return result
    except ValueError as e:
        print(f"エラー: '{hex_str}'は有効な16進数ではありません")
        return None

# 使用例
print(safe_hex_to_decimal('ff'))        # 出力: 255
print(safe_hex_to_decimal('0xff'))      # 出力: 255
print(safe_hex_to_decimal('#ff8040'))   # 出力: 16744512
print(safe_hex_to_decimal('zzz'))       # エラーメッセージ表示、None返却
print(safe_hex_to_decimal('xyz'))       # エラーメッセージ表示、None返却

より詳細なバリデーションを行う場合は、正規表現を使って事前チェックすることもできます。

import re

def validate_and_convert_hex(hex_str):
    """
    16進数文字列をバリデーションして変換
    """
    # 16進数パターン(0xプレフィックス、#記号、負の数にも対応)
    pattern = r'^-?(?:#|0x)?[0-9a-fA-F]+$'
    
    hex_str = hex_str.strip()
    
    if re.match(pattern, hex_str):
        # #や0xを除去
        cleaned = hex_str.replace('#', '').replace('0x', '').replace('0X', '')
        if hex_str.startswith('-'):
            cleaned = '-' + cleaned.replace('-', '')
        return int(cleaned, 16)
    else:
        raise ValueError(f"'{hex_str}'は有効な16進数形式ではありません")

# 使用例
try:
    print(validate_and_convert_hex('ff'))         # 出力: 255
    print(validate_and_convert_hex('#ff8040'))    # 出力: 16744512
    print(validate_and_convert_hex('-0xff'))      # 出力: -255
    print(validate_and_convert_hex('xyz'))        # ValueError発生
except ValueError as e:
    print(e)

実践的な応用例とコード集

続いては、実際のプログラミングで役立つ応用例を確認していきます。

RGB色コードの相互変換

Webデザインやグラフィックス処理では、RGB値と16進数色コードの相互変換が頻繁に必要になります。実用的な関数を実装してみましょう。

# RGB値から16進数色コードを生成
def rgb_to_hex(r, g, b):
    """
    RGB値(0-255)を16進数色コードに変換
    """
    return f"#{r:02x}{g:02x}{b:02x}"

# 16進数色コードからRGB値を取得
def hex_to_rgb(hex_color):
    """
    16進数色コードをRGB値に変換
    """
    # #を除去
    hex_color = hex_color.lstrip('#')
    
    # RGB成分を抽出
    r = int(hex_color[0:2], 16)
    g = int(hex_color[2:4], 16)
    b = int(hex_color[4:6], 16)
    
    return (r, g, b)

# 使用例
print(rgb_to_hex(255, 128, 64))   # 出力: #ff8040
print(rgb_to_hex(0, 128, 255))    # 出力: #0080ff

rgb = hex_to_rgb("#ff8040")
print(rgb)  # 出力: (255, 128, 64)

rgb2 = hex_to_rgb("#0080ff")
print(rgb2)  # 出力: (0, 128, 255)

# 相互変換の確認
original_rgb = (255, 100, 50)
hex_code = rgb_to_hex(*original_rgb)
restored_rgb = hex_to_rgb(hex_code)
print(f"元の値: {original_rgb}")
print(f"16進数: {hex_code}")
print(f"復元値: {restored_rgb}")
print(f"一致: {original_rgb == restored_rgb}")

色の明るさを調整する関数も作成できます。

def adjust_brightness(hex_color, factor):
    """
    色の明るさを調整(factorは0.0-2.0程度)
    """
    r, g, b = hex_to_rgb(hex_color)
    
    # 各成分に係数を掛けて調整
    r = min(255, int(r * factor))
    g = min(255, int(g * factor))
    b = min(255, int(b * factor))
    
    return rgb_to_hex(r, g, b)

# 使用例
base_color = "#ff8040"
print(f"元の色: {base_color}")
print(f"50%暗く: {adjust_brightness(base_color, 0.5)}")
print(f"50%明るく: {adjust_brightness(base_color, 1.5)}")
# 出力:
# 元の色: #ff8040
# 50%暗く: #7f4020
# 50%明るく: #ffc060

バイトデータの16進数表現

バイナリデータを扱う際には、バイト列を16進数文字列に変換したり、その逆を行ったりする処理が必要になります。

# バイト列を16進数文字列に変換
data = b'\xff\x80\x40'

# hex()メソッドを使用
hex_string = data.hex()
print(hex_string)  # 出力: ff8040

# スペース区切りで表示
hex_spaced = ' '.join(f'{byte:02x}' for byte in data)
print(hex_spaced)  # 出力: ff 80 40

# 16進数文字列をバイト列に変換
hex_str = "ff8040"
byte_data = bytes.fromhex(hex_str)
print(byte_data)  # 出力: b'\xff\x80@'

# スペース区切りでもOK
hex_str2 = "ff 80 40"
byte_data2 = bytes.fromhex(hex_str2)
print(byte_data2)  # 出力: b'\xff\x80@'

# ファイルのようなバイトデータの16進ダンプ
def hex_dump(data, bytes_per_line=16):
    """
    バイトデータを16進数ダンプ形式で表示
    """
    for i in range(0, len(data), bytes_per_line):
        chunk = data[i:i+bytes_per_line]
        hex_part = ' '.join(f'{byte:02x}' for byte in chunk)
        ascii_part = ''.join(chr(byte) if 32 <= byte < 127 else '.' for byte in chunk)
        print(f"{i:08x}  {hex_part:<{bytes_per_line*3}}  {ascii_part}")

# 使用例
sample_data = b'Hello, World!\xff\xfe\xfd'
hex_dump(sample_data)
# 出力:
# 00000000  48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21 ff fe fd  Hello, World!...

複数の数値を一括変換する

実務では、複数の数値をまとめて変換する必要があることが多いでしょう。リスト内包表記を使うと、効率的に処理できます。

# 10進数のリストを16進数に一括変換
decimal_numbers = [10, 15, 16, 255, 256, 4095, 65535]

# 0xプレフィックス付き
hex_list1 = [hex(n) for n in decimal_numbers]
print(hex_list1)
# 出力: ['0xa', '0xf', '0x10', '0xff', '0x100', '0xfff', '0xffff']

# プレフィックスなし(小文字)
hex_list2 = [format(n, 'x') for n in decimal_numbers]
print(hex_list2)
# 出力: ['a', 'f', '10', 'ff', '100', 'fff', 'ffff']

# プレフィックスなし(大文字、4桁ゼロ埋め)
hex_list3 = [format(n, '04X') for n in decimal_numbers]
print(hex_list3)
# 出力: ['000A', '000F', '0010', '00FF', '0100', '0FFF', 'FFFF']

# 16進数のリストを10進数に変換
hex_strings = ['a', 'ff', '100', 'fff', 'ffff']
decimal_list = [int(h, 16) for h in hex_strings]
print(decimal_list)
# 出力: [10, 255, 256, 4095, 65535]

# 辞書形式で対応表を作成
conversion_table = {h: int(h, 16) for h in hex_strings}
print(conversion_table)
# 出力: {'a': 10, 'ff': 255, '100': 256, 'fff': 4095, 'ffff': 65535}

IPアドレスを16進数で表現する例も見てみましょう。

def ip_to_hex(ip_address):
    """
    IPv4アドレスを16進数表現に変換
    """
    octets = ip_address.split('.')
    hex_octets = [format(int(octet), '02x') for octet in octets]
    return '0x' + ''.join(hex_octets)

def hex_to_ip(hex_value):
    """
    16進数表現をIPv4アドレスに変換
    """
    # 0xを除去
    hex_clean = hex_value.replace('0x', '')
    
    # 8桁になるようゼロ埋め
    hex_clean = hex_clean.zfill(8)
    
    # 2桁ずつ分割して10進数に変換
    octets = [str(int(hex_clean[i:i+2], 16)) for i in range(0, 8, 2)]
    return '.'.join(octets)

# 使用例
ip = "192.168.1.1"
hex_ip = ip_to_hex(ip)
print(f"IPアドレス: {ip}")
print(f"16進数表現: {hex_ip}")

restored_ip = hex_to_ip(hex_ip)
print(f"復元: {restored_ip}")
# 出力:
# IPアドレス: 192.168.1.1
# 16進数表現: 0xc0a80101
# 復元: 192.168.1.1

まとめ

Pythonでの16進数変換は、hex()関数とint()関数を使うことで簡単に実現できます。10進数から16進数への変換にはhex()を、16進数から10進数への変換にはint(x, 16)を使用するのが基本です。

hex()関数は「0x」プレフィックス付きの小文字の文字列を返すため、必要に応じてスライスやreplace()で除去できます。また、format()関数やf文字列を使えば、プレフィックスなしの出力、大文字小文字の指定、ゼロ埋めなど、柔軟な形式で変換が可能でしょう。

int()関数は、0xプレフィックスや#記号の有無、アルファベットの大文字小文字に関わらず変換でき、負の数やアンダースコア区切りの文字列にも対応しています。実用的なプログラムでは、try-except文を使った適切なエラー処理を実装することが重要です。

RGB色コードの相互変換、バイトデータの16進数表現、IPアドレスの変換など、実践的な応用例も豊富にあります。これらのテクニックを身につけることで、Web開発、ネットワークプログラミング、バイナリデータ処理など、様々な場面で活用できるのです。

16進数変換をマスターすることで、Pythonでのプログラミングの幅が大きく広がります。ぜひ実際にコードを動かしながら、理解を深めていきましょう。