はじめに
書籍には ISBN (国際標準図書番号) というコードが付いています。
例えば古い書籍を調べていたとします。この書籍の第 2 版の ISBN-10 コードが Google 先生で調べてみても判りませんでした。
版 | ISBN-10 | 出版年 |
---|---|---|
第 1 版 | 3519023385 | 1977 |
第 2 版 | ?????????? | 1981 |
第 3 版 | 3519223384 | 1984 |
第 4 版 | 3519323389 | 1986 |
...ですが、この ISBN コード、よく見ると前から 5 文字目が連番になっているようです。恐らく第 2 版は 351912338? だと思われるのですが、最後の一文字 (チェックディジット) が判らないため、10 桁の ISBN コードを得ることができません。
実際には前 9 桁が判れば Google 先生で引っ掛かる事が多いのですが、折角なので Delphi で ISBN のチェックディジットを求めてみたいと思います。
See also:
コード (ISBN-10)
チェックディジットの求め方は Wikipedia にある通りですが、英語版 Wikipedia の説明の方が親切だと思います。
See also:
Delphi の場合
使用する Delphi は 10.4 Sydney です。インライン変数宣言を使っているため、10.3 Rio よりも前の Delphi をお使いの場合にはコードの修正が必要となります。
数字以外の文字入力を無視するようにしたため、ソースコードが少し長くなっていますが、3-519-02338-5
のようにハイフン込みで入力しても、チェックディジットを正しく計算してくれます。
program ISBN10;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
const
STARTNUM = Ord('0');
begin
Write('Input ISBN-10: ');
var s := StringOfChar('0', 9);
var idx := 1;
while not Eoln do
begin
var c: Char;
Read(c);
if CharInSet(c, ['0'..'9']) then
begin
s[idx] := c;
idx := idx + 1;
if idx = 10 then
Break;
end;
end;
Writeln;
var v1 := 0;
for var i in [1..9] do
v1 := v1 + (Ord(s[i]) - STARTNUM) * (11 - i);
var v2 := (11 - (v1 mod 11)) mod 11;
var cd: Char;
if v2 = 10 then
cd := 'X'
else
cd := Chr(STARTNUM + v2);
Writeln('The check digit of ', s, ' is ', cd, '.');
end.
See also:
標準 Pascal の場合
折角なので標準 Pascal でも書いてみました。Delphi のコードは標準 Pascal への移植を意識したものになっているため、大きな違いはありません。検証に使ったのは Pascal-P5 です。
program ISBN10(Input, Output);
label
1;
var
i, idx, sn, v1, v2: Integer;
s: packed array [1..9] of Char;
c, cd: Char;
begin
sn := Ord('0');
Write('Input ISBN-10: ');
s := '000000000';
idx := 1;
while not Eoln do
begin
Read(c);
if c in ['0'..'9'] then
begin
s[idx] := c;
idx := idx + 1;
if idx = 10 then
goto 1;
end;
end;
Writeln;
1:
v1 := 0;
for i:=1 to 9 do
v1 := v1 + (Ord(s[i]) - sn) * (11 - i);
v2 := (11 - (v1 mod 11)) mod 11;
if v2 = 10 then
cd := 'X'
else
cd := Chr(sn + v2);
Writeln('The check digit of ', s, ' is ', cd, '.');
end.
See also:
コード (ISBN-13)
ISBN-13 のチェックディジットも求めてみましょう。こちらのほうがアルゴリズム的にはスッキリ書けます。
Delphi の場合
ISBN-10 のものと比べて、コードが少し短くなっています。
program ISBN13;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
const
STARTNUM = Ord('0');
WEIGHT: array [Boolean] of Integer = (3, 1);
begin
Write('Input ISBN-13: ');
var s := StringOfChar('0', 12);
var idx := 1;
while not Eoln do
begin
var c: Char;
Read(c);
if CharInSet(c, ['0'..'9']) then
begin
s[idx] := c;
idx := idx + 1;
if idx = 13 then
Break;
end;
end;
Writeln;
var v1 := 0;
for var i in [1..12] do
v1 := v1 + (Ord(s[i]) - STARTNUM) * WEIGHT[Odd(i)];
var v2 := 10 - (v1 mod 10);
var cd := Chr(STARTNUM + v2);
Writeln('The check digit of ', s, ' is ', cd, '.');
end.
標準 Pascal の場合
こちらもコードが少し短くなっています。
program ISBN13(Input, Output);
label
1;
var
i, idx, sn, v1, v2: Integer;
s: packed array [1..12] of Char;
c, cd: Char;
w: array [Boolean] of Integer;
begin
sn := Ord('0');
w[False] := 3; w[True] := 1;
Write('Input ISBN-13: ');
s := '000000000000';
idx := 1;
while not Eoln do
begin
Read(c);
if c in ['0'..'9'] then
begin
s[idx] := c;
idx := idx + 1;
if idx = 13 then
goto 1;
end;
end;
Writeln;
1:
v1 := 0;
for i:=1 to 12 do
v1 := v1 + (Ord(s[i]) - sn) * w[Odd(i)];
v2 := 10 - (v1 mod 10);
cd := Chr(sn + v2);
Writeln('The check digit of ', s, ' is ', cd, '.');
end.
ISBN-10 と ISBN-13 の相互変換
ISBN-10 と ISBN-13 は変換可能です。例として次の ISBN コードを変換してみます。
ISBN | コード |
---|---|
ISBN-10 | 3519023385 |
ISBN-13 | 9783519023388 |
ISBN-10 から ISBN-13 へ
ISBN-13 のプログラムを使います。固定の 接頭記号 と ISBN-10 の先頭 9 文字を入力します (10 文字のままでも構いません)。
接頭記号 | コード | CD |
---|---|---|
978 1 | 351902338 | 5 |
ISBN-13 コード 9783519023388
が得られました。
ISBN-13 から ISBN-10 へ
ISBN-10 のプログラムを使います。接頭記号の先頭 3 文字と最後のチェックディジットを抜いた 9 文字を入力します (先頭 3 文字を抜いた 10 文字でも構いません)。
接頭記号 | コード | CD |
---|---|---|
978 1 | 351902338 | 8 |
ISBN-10 コード 3519023385
が得られました。
おわりに
冒頭の 351912338? のチェックディジットは X
です。ISBN-10 は 351912338X
だったのですね。
Google 先生にこのコードを尋ねても大した情報は得られないという...ちなみに書籍名は**『Compilerbau: Eine Einführung (第 2 版)』**です。
今年は Delphi 25 周年、Pascal 50 周年という事でイロイロな Delphi / Pascal 関連書籍を読んだり調べたりしました。
See also: