数値 <-> n 進数 変換 +α

機能:

 n 進数と数値を相互に変換します。Excel の桁文字列とインデックスを相互に変換する関数も用意されています。


解説:

 引数や戻り値に関してはソースコード内のコメントを参照して下さい。関数群はユニットになっていますので、"RadixConv.pas" として保存して利用して下さい。


ソースコード:

unit RadixConv;

interface

uses
  SysUtils, Math;

type
  TRadixRange  = 2..256;
  TDigitsRange = 0..255;

const
  FRadixTable = '0123456789ABCDEF';

// 数値 -> n 進数文字列
function IntToStrEx(const Value: Int64; const Radix: TRadixRange = 10const Digits: TDigitsRange = 0const RadixTable: string = ''): string;
// n 進数文字列 -> 数値
function StrToIntEx(const s: stringconst Radix: TRadixRange = 10const RadixTable: string = ''): Int64;

// 数値 -> Excel 桁文字列
function IntToExcelHexacos(const Value: Int64): string;
// Excel 桁文字列 -> 数値
function ExcelHexacosToInt(const s: string): Int64;

implementation

function IntToStrEx(const Value: Int64; const Radix: TRadixRange = 10const Digits: TDigitsRange = 0const RadixTable: string = ''): string;
// -----------------------------------------------------------------------------
// 数値 -> n 進数文字列
//
// 引数
//   Value     : 変換する数値
//   Radix     : 基数 (Radix 進数) Radix >= 2
//   Digits    : 表示桁 (0 で自動)
//   RadixTable: 桁文字テーブル
//
// 戻り値
//   Radix 進数文字列
// -----------------------------------------------------------------------------
var
  i: Integer;
  dRadixTable: String;
  dValue: UInt64;
begin
  result := '';
  // Radix Table
  if RadixTable = '' then
    dRadixTable := FRadixTable
  else
    dRadixTable := RadixTable;
  // Error
  if Length(dRadixTable) < Radix then
    Exit;
  // Calc
  dValue := Value;
  for i:=1 to 64 do
    begin
      result := dRadixTable[(dValue mod Radix) + 1] + result;
      dValue := dValue div Radix;
      if dValue = 0 then
        Break;
      if (Digits > 0and (i = Digits) then
        Break;
    end;
  // Format
  if Digits > 0 then
    begin
      result := Copy(result, Min(1, Digits - Length(result) + 1), Digits);
      result := StringOfChar(dRadixTable[1], Digits - Length(result)) + result;
    end;
end;

function StrToIntEx(const s: stringconst Radix: TRadixRange = 10const RadixTable: string = ''): Int64;
// -----------------------------------------------------------------------------
// n 進数文字列 -> 数値
//
// 引数
//   s         : Radix 進数文字列
//   Radix     : 基数 (Radix 進数) Radix >= 2
//   RadixTable: 桁文字テーブル
//
// 戻り値
//   数値
// -----------------------------------------------------------------------------
var
  i: Byte;
  dRadixTable: String;
  dValue: Byte;
  Loop: Byte;
  s2: string;
begin
  result := 0;
  // Radix Table
  if RadixTable = '' then
    dRadixTable := FRadixTable
  else
    dRadixTable := RadixTable;
  // Error
  if Length(dRadixTable) < Radix then
    Exit;
  // Loop Counter
  s2 := Trim(s);
  for i:=1 to Length(s2) do
    if s2[i] = dRadixTable[1then
      s2[i] := ' '
    else
      Break;
  s2 := Trim(s2);
  Loop := Length(s2);
  // Calc
  for i:=1 to Loop do
    begin
      result := result * Radix;
      dValue := Pos(s2[i], dRadixTable);
      if (dValue = 0or (dValue > Radix) then
        begin
          result := 0;
          Break;
        end;
      result := result + (dValue - 1);
    end;
end;

function IntToExcelHexacos(const Value: Int64): string;
// -----------------------------------------------------------------------------
// 数値 -> Excel 桁文字列
//
// 引数
//   Value : 変換する数値
//
// 戻り値
//   Excel 桁形式 26 進数文字列
// -----------------------------------------------------------------------------
const
  RadixTable = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var
  dValue: UInt64;
  dDigits: TDigitsRange;
begin
  // Calc
  dValue  := 0;
  dDigits := 0;
  repeat
    Inc(dDigits);
    dValue := dValue + Trunc(IntPower(26, dDigits));
  until (Value < dValue);
  dValue := dValue - Trunc(IntPower(26, dDigits));
  result := IntToStrEx(Value - dValue, 26, dDigits, RadixTable);
end;

function ExcelHexacosToInt(const s: string): Int64;
// -----------------------------------------------------------------------------
// Excel 桁文字列 -> 数値
//
// 引数
//   s : Excel 桁形式 26 進数文字列
//
// 戻り値
//   数値
// -----------------------------------------------------------------------------
const
  RadixTable = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var
  i: Integer;
  s2: string;
begin
  s2 := Trim(s);
  // Calc
  result := StrToIntEx(s2, 26, RadixTable);
  for i:=1 to Length(s2)-1 do
    result := result + Trunc(IntPower(26, i));
end;
end.

評価コード:

var
  s: string;
  v: Int64;
begin
  Memo1.Lines.Clear;

  Memo1.Lines.Add('[Decimal -> Hex]');
  Memo1.Lines.Add('-10');

  // -10 を Byte (8 bit) の 16 進数表現で表示
  s := IntToStrEx(Byte(-10), 16, SizeOf(Byte) * 2);
  Memo1.Lines.Add('Byte: '     + s);
  // -10 を Word (16 bit) の 16 進数表現で表示
  s := IntToStrEx(Word(-10), 16, SizeOf(Word) * 2);
  Memo1.Lines.Add('Word: '     + s);
  // -10 を Longword (32 bit) の 16 進数表現で表示
  s := IntToStrEx(Longword(-10), 16, SizeOf(Longword) * 2);
  Memo1.Lines.Add('Longword: ' + s);
  // -10 を UInt64 (64 bit) の 16 進数表現で表示
  s := IntToStrEx(-1016, SizeOf(UInt64) * 2);
  Memo1.Lines.Add('UInt64: '   + s);

  Memo1.Lines.Add('');

  Memo1.Lines.Add('[Hex -> Decimal]');

  // 'FF' を 16 進数 -> 10 進値
  s := 'FF';
  Memo1.Lines.Add('0x' + s);
  v := Shortint(StrToIntEx(s, 16));
  Memo1.Lines.Add('Shortint: ' + IntToStr(v));
  v := Byte(StrToIntEx(s, 16));
  Memo1.Lines.Add('Byte: '     + UIntToStr(v));
  v := Smallint(StrToIntEx(s, 16));
  Memo1.Lines.Add('Smallint: ' + IntToStr(v));
  v := Word(StrToIntEx(s, 16));
  Memo1.Lines.Add('Word: '     + UIntToStr(v));
  Memo1.Lines.Add('');

  // 'FFFF' を 16 進数 -> 10 進値
  s := 'FFFF';
  Memo1.Lines.Add('0x' + s);
  v := Smallint(StrToIntEx(s, 16));
  Memo1.Lines.Add('Smallint: ' + IntToStr(v));
  v := Word(StrToIntEx(s, 16));
  Memo1.Lines.Add('Word: '     + UIntToStr(v));
  v := Longint(StrToIntEx(s, 16));
  Memo1.Lines.Add('Longint: '  + IntToStr(v));
  v := Longword(StrToIntEx(s, 16));
  Memo1.Lines.Add('Longword: ' + UIntToStr(v));
  Memo1.Lines.Add('');

  // 'FFFFFFFF' を 16 進数 -> 10 進値
  s := 'FFFFFFFF';
  Memo1.Lines.Add('0x' + s);
  v := Longint(StrToIntEx(s, 16));
  Memo1.Lines.Add('Longint: '  + IntToStr(v));
  v := Longword(StrToIntEx(s, 16));
  Memo1.Lines.Add('Longword: ' + UIntToStr(v));
  v := StrToIntEx(s, 16);
  Memo1.Lines.Add('Int64: '    + IntToStr(v));
  v := UInt64(StrToIntEx(s, 16));
  Memo1.Lines.Add('UInt64: '   + UIntToStr(v));
  Memo1.Lines.Add('');

  // 'FFFFFFFFFFFFFFFF' を 16 進数 -> 10 進値
  s := 'FFFFFFFFFFFFFFFF';
  Memo1.Lines.Add('0x' + s);
  v := StrToIntEx(s, 16);
  Memo1.Lines.Add('Int64: '    + IntToStr(v));
  v := UInt64(StrToIntEx(s, 16));
  Memo1.Lines.Add('UInt64: '   + UIntToStr(v));
end;

 16 進数以上を扱う場合には、基数の桁文字テーブルを自前で定義しなくてはなりません。

var
  dRadixTable: string;
  v: Int64;
  s: string;
begin
  // BASE32
  v := 100;
  dRadixTable :=               'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  dRadixTable := dRadixTable + '234567';
  s := IntToStrEx(v, 320, dRadixTable);
  Memo1.Lines.Add(s);

  // BASE64
  v := 100;
  dRadixTable :=               'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  dRadixTable := dRadixTable + 'abcdefghijklmnopqrstuvwxyz';
  dRadixTable := dRadixTable + '+/';
  s := IntToStrEx(v, 640, dRadixTable);
  Memo1.Lines.Add(s);
end;

 Excel 桁文字列は以下のようにして扱います。

var
  i: Integer;
  v: Int64;
  s: string;
begin
  Memo1.Lines.Clear;
  for i:=0 to 999 do
    begin
      s := IntToExcelHexacos(i);
      v := ExcelHexacosToInt(s);
      Memo1.Lines.Add(IntToStr(i) + ' : ' + s + ' -> ' + IntToStr(v));
    end;
end;

 BACK