JavaScriptを利用した開発において、数値を16進数に変換したり、逆に16進数の文字列を数値に戻したりする操作は非常に頻繁に発生します。

Web制作におけるカラーコードの操作や、バイナリデータの解析、暗号化処理など、16進数が活躍する場面は多岐にわたります。

基本的な変換方法を正しく理解しておくことで、データ処理のバグを減らし、コードの可読性を大幅に向上させることが可能です。

本記事では、初心者から中級者までが活用できるJavaScriptでの16進数変換テクニックを網羅的に解説します。

数値から16進数文字列へ変換する方法

JavaScriptで数値を16進数の文字列に変換する最も標準的な方法は、toStringメソッドを使用することです。

通常、toString()は引数なしで実行すると10進数の文字列を返しますが、引数に基数を指定することで任意の進数に変換できます。

16進数へ変換する場合は、引数に「16」を指定するだけで簡単に実行可能です。

toString(16)の基本的な使い方

まずは、10進数の整数を16進数の文字列に変換する基本的なコード例を見ていきましょう。

JavaScript
// 10進数の数値を定義
const decimalValue = 255;

// toString(16)を使用して16進数文字列に変換
const hexString = decimalValue.toString(16);

// 結果を表示
console.log(hexString);
実行結果
ff

このように、数値オブジェクトが持つメソッドを呼び出すだけで、簡単に16進数表記を得ることができます。

注意点として、変換後のアルファベットはデフォルトで小文字になります。

もし大文字の16進数が必要な場合は、toUpperCase()メソッドを組み合わせて使用してください。

JavaScript
const decimalValue = 255;
// 変換後に大文字化する
const upperHexString = decimalValue.toString(16).toUpperCase();

console.log(upperHexString);
実行結果
FF

ゼロパディング(桁を揃える方法)

色を扱うコードやバイナリデータの表示では、16進数を「05」や「0A」のように2桁固定で表示したい場合があります。

toString(16)だけでは、数値が15以下の場合に1桁の文字列になってしまいます。

これを防ぐためには、padStartメソッドを利用するのが非常に効率的です。

JavaScript
const colorValue = 10;
// 2文字に満たない場合、左側を '0' で埋める
const paddedHex = colorValue.toString(16).padStart(2, '0');

console.log(paddedHex);
実行結果
0a

この手法は、カラーコードを生成する際の「R, G, B」それぞれの値を結合する際などに必須のテクニックとなります。

16進数文字列から数値へ変換する方法

次に、外部から受け取った「ff」や「0x1A」といった16進数文字列を、プログラムで計算可能な数値型に変換する方法を解説します。

JavaScriptには、文字列を指定した進数で解析するためのparseInt関数が用意されています。

parseInt関数の活用

parseIntの第2引数に「16」を指定することで、文字列を16進数として解釈します。

JavaScript
const hexInput = "ff";
// 第2引数に16を指定してパースする
const decimalOutput = parseInt(hexInput, 16);

console.log(decimalOutput);
実行結果
255

この関数は非常に柔軟であり、文字列の先頭に「0x」が付いていても正しく処理してくれます。

しかし、予期せぬ挙動を防ぐために、常に第2引数を明示することが推奨されます。

Number関数と0xプレフィックス

文字列の先頭に「0x」が付与されていることが保証されている場合、Number()関数を使用することも可能です。

JavaScript
const hexWithPrefix = "0x1A";
// 自動的に16進数として解釈される
const result = Number(hexWithPrefix);

console.log(result);
実行結果
26

ただし、空文字や不正な形式の文字列を渡すとNaN(Not a Number)や「0」を返すことがあるため、バリデーションが必要です。

大きな数値(BigInt)の16進数変換

JavaScriptの標準的なNumber型は、内部的に64ビット浮動小数点数として扱われるため、扱える整数の大きさに限界があります。

非常に大きなIDや暗号鍵などを扱う場合、数値が精度を失ってしまうリスクがあります。

そうしたケースでは、BigIntを使用するのが正しい選択です。

BigIntでの変換手順

BigIntでも、通常の数値型と同様にtoString(16)を使用できます。

JavaScript
// 非常に大きな数値(末尾にnを付ける)
const largeNumber = 9007199254740991000n;
const bigHex = largeNumber.toString(16);

console.log(bigHex);
実行結果
7cfffffffffffff8

逆に、巨大な16進数文字列をBigIntに戻す場合は、文字列の先頭に「0x」を付加してコンストラクタに渡します。

JavaScript
const bigHexInput = "7cfffffffffffff8";
// 0xを付加してBigIntに変換
const backToBigInt = BigInt("0x" + bigHexInput);

console.log(backToBigInt);
実行結果
9007199254740991000n

これにより、桁数の多い16進数データも精度を落とすことなく安全に扱うことが可能になります。

実践的な応用:カラーコードの変換

JavaScriptでの16進数変換が最もよく使われる例の一つが、RGB形式と16進数カラーコードの相互変換です。

Webデザインの動的な変更機能を実装する際に非常に役立ちます。

RGBから16進数への変換関数

3つの数値(赤、緑、青)を受け取り、一つのカラーコード文字列(#RRGGBB)を生成する関数を実装してみましょう。

JavaScript
function rgbToHex(r, g, b) {
  // 各要素を16進数化して2桁でパディングし、結合する
  const toHex = (val) => val.toString(16).padStart(2, '0');
  return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}

console.log(rgbToHex(255, 165, 0)); // オレンジ色
実行結果
#ffa500

16進数からRGBへのパース

逆に、カラーコードを数値の配列に分解する方法も重要です。

substringメソッドで文字列を分割し、それぞれをparseIntで数値に戻します。

JavaScript
function hexToRgb(hex) {
  // 先頭の#を除去
  const cleanHex = hex.startsWith('#') ? hex.slice(1) : hex;
  
  // 2文字ずつ分割して数値化
  const r = parseInt(cleanHex.substring(0, 2), 16);
  const g = parseInt(cleanHex.substring(2, 4), 16);
  const b = parseInt(cleanHex.substring(4, 6), 16);
  
  return { r, g, b };
}

console.log(hexToRgb("#ffa500"));
実行結果
{ "r": 255, "g": 165, "b": 0 }

バイナリデータと16進数変換

ファイルアップロードや通信プロトコルの解析を行う際、Uint8Arrayなどの型付き配列を16進数文字列に変換するニーズがあります。

これは、バイナリデータをログに出力して中身を確認する際に非常に便利です。

Uint8Arrayを16進数文字列にする

配列の各要素をループで処理し、16進数に変換して結合していきます。

JavaScript
const bytes = new Uint8Array([72, 101, 108, 108, 111]); // "Hello" の文字コード
const hexArray = Array.from(bytes).map(b => b.toString(16).padStart(2, '0'));
const hexDump = hexArray.join(' ');

console.log(hexDump);
実行結果
48 65 6c 6c 6f

大量のデータを処理する場合は、パフォーマンスを考慮してmapではなくループを使用するなどの最適化も検討してください。

よくあるエラーと注意点

16進数変換を行う際には、いくつか注意すべき落とし穴があります。

これらを事前に把握しておくことで、デバッグの時間を短縮できます。

不正な文字列の入力

parseInt("ZZ", 16)のように、16進数として成立しない文字列を入力すると、結果はNaNになります。

ユーザーからの入力を受け取る場合は、正規表現などを用いて事前チェックを行うことが推奨されます。

JavaScript
const input = "G1";
const value = parseInt(input, 16);

if (isNaN(value)) {
  console.log("エラー:有効な16進数ではありません。");
}

ビット演算の落とし穴

JavaScriptのビット演算子は、内部的に32ビット整数としてオペランドを扱います。

そのため、非常に大きな数値をビット演算で操作しようとすると、符号が反転したり、上位ビットが切り捨てられたりすることがあります。

32ビット(0xFFFFFFFF)を超える値を扱う際は、前述のBigIntを使用するようにしましょう。

パフォーマンス比較:最適な方法の選択

16進数変換において、処理速度が問題になることは稀ですが、ループ内で数万回実行されるようなケースでは注意が必要です。

例えば、数値から文字列への変換において、toString(16)は十分に高速です。

しかし、独自のルックアップテーブル(あらかじめ変換済みの配列を用意しておく手法)を用いると、さらに高速化できる場合があります。

手法メリットデメリット
toString(16)標準的で読みやすく、汎用性が高い。極端に大量のループ内では若干のオーバーヘッドがある。
parseInt(s, 16)文字列からの変換に最適で、柔軟性が高い。不正な文字に対してNaNを返すためチェックが必要。
ルックアップテーブル変換済みの値を参照するため、最速の実行が可能。コードが複雑になり、メモリをわずかに消費する。

一般的なアプリケーション開発においては、コードの保守性を優先し、標準メソッドであるtoStringparseIntを利用するのがベストプラクティスです。

まとめ

JavaScriptにおける16進数変換は、標準のメソッドを正しく組み合わせることで非常にシンプルに実装できます。

数値から文字列へはtoString(16)、文字列から数値へはparseInt(str, 16)を利用するのが基本です。

また、実務レベルではpadStart(2, '0')によるゼロパディングや、巨大な数値を扱うためのBigIntの活用が重要になります。

カラーコードの生成やバイナリデータの解析など、具体的な利用シーンを想定してこれらのテクニックを使い分けてください。

正確な進数変換をマスターすることで、JavaScriptによるデータ操作の幅はさらに広がることでしょう。