7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

DelphiAdvent Calendar 2020

Day 16

Delphi で ISBN のチェックディジットを計算してみる

Last updated at Posted at 2020-12-15

はじめに

書籍には 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 のようにハイフン込みで入力しても、チェックディジットを正しく計算してくれます。

isbn10.dpr
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 です。

isbn10.pas
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 のものと比べて、コードが少し短くなっています。

isbn13.dpr
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 の場合

こちらもコードが少し短くなっています。

isbn13.pas
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

image.png
ISBN-13 コード 9783519023388 が得られました。

ISBN-13 から ISBN-10 へ

ISBN-10 のプログラムを使います。接頭記号の先頭 3 文字と最後のチェックディジットを抜いた 9 文字を入力します (先頭 3 文字を抜いた 10 文字でも構いません)。

接頭記号 コード CD
978 1 351902338 8

image.png
ISBN-10 コード 3519023385 が得られました。

おわりに

冒頭の 351912338? のチェックディジットは X です。ISBN-10 は 351912338X だったのですね。
image.png
Google 先生にこのコードを尋ねても大した情報は得られないという...ちなみに書籍名は**『Compilerbau: Eine Einführung (第 2 版)』**です。

今年は Delphi 25 周年、Pascal 50 周年という事でイロイロな Delphi / Pascal 関連書籍を読んだり調べたりしました。

See also:

  1. 一部の国では接頭記号が 979 であるため、ISBN-10 から ISBN-13 への変換は完全ではありません。 2

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?