書籍ISBNのチェックディジット計算と10桁⇔13桁変換

なんとなく、作ってみた。ただし、コード中のコメントにも書いたとおり、接頭記号 978 だけでなく、979 が増えてきたら、たぶん無効になるのだろう。
ただ変換するだけなら既に WEB 上にそういうサービスはいくつも見つかる筈なので、わざわざこんなもの作る必要はないのだけれど、ちょっと自分のページの中で(amazon へのリンクを作成するために、当面の間だけでも)使いたかったので、PHP で書いてみた。……まだきちんと検証はしていないので、間違いがないとはいえない。

checkdigit.php

<?php

// ISBN10 のチェックディジットの算出
function ChkDgt10($nine) {
    /* 計算方法
        (1) 10桁コードの各桁の桁数(d)と値(Vd)の積の合計を求める(ただし d > 1)。
            V10×10 + V9×9 + V8×8 + … + V2×2
        (2) チェックディジット = 11 −((1)の答を 11 で割った剰余) となる。
            ただし、求めた数字が 10 の場合は X とし、11 の場合は 0 とする。
    */

    // $nine : チェックディジットを除いた9桁の数字
    // $nine = trim(str_replace('-', '', $nine)); // この行は必要に応じて活殺
    if (strlen($nine) === 9) {
        $sum = 0;
        for ($i = 0; $i < 9; $i ++) {
            $dgt = 10 - $i; // 添字(オフセット)と桁数の関係
            $sum += (int)$nine[$i] * $dgt;
        }
        $ChkDgt = 11 - ($sum % 11);
        if ($ChkDgt === 10) $ChkDgt = 'X';
        if ($ChkDgt === 11) $ChkDgt = '0';
        return $ChkDgt;
    } else {
        return FALSE;
    }
}

// ISBN13 のチェックディジットの算出
function ChkDgt13($twelve) {
    /* 計算方法
        (1) (13桁コードの左から奇数桁の数字の合計×1)と(偶数桁の数字の合計×3)の合計を求める。
        (2) チェックディジット = 10 −((1)の答の下1桁の数字) となる。
            ただし、求めた数字が 0 または 10 の場合はチェックディジットを 0 とする。
            ※((1)の答の下1桁の数字)とは((1)の答を10で割った剰余)と同値。
    */

    // $twelve : チェックディジットを除いた12桁の数字
    // $twelve = trim(str_replace('-', '', $twelve)); // この行は必要に応じて活殺

    // 文字数が12桁であり、かつ左から3桁が 978 または 979
    if (strlen($twelve) === 12 && (substr($twelve, 0, 3) == '978' || substr($twelve, 0, 3) == '979')) {
        $odd_sum = $even_sum = 0;
        $odd_sum  = 9 + (int)$twelve[2] + (int)$twelve[4] + (int)$twelve[6] + (int)$twelve[8] + (int)$twelve[10];
        $even_sum = 7 + (int)$twelve[3] + (int)$twelve[5] + (int)$twelve[7] + (int)$twelve[9] + (int)$twelve[11];
        // ↑添字はオフセット 0 から始まるので、桁数-1 (奇数と偶数が逆転)となる
        $sum = $odd_sum + $even_sum * 3;
        $ChkDgt = 10 - ($sum % 10);
        if ($ChkDgt === 10) $ChkDgt = '0';
        return $ChkDgt;
    } else {
        return FALSE;
    }
}

// ISBN13 ⇒ ISBN10 に変換
function Isbn13210($ISBN13) {
    /* ※ 接頭記号が 979 の場合も、978 と同様の変換でOKなのかは未確認。
        というか、978 で不足した場合に 979 を用いるということらしいので、
        接頭記号取ったら重複する(区別できない)場合も出てくるということか?
        つまり、いずれ変換不可になるってことだろう。
    */

    $ISBN13 = trim(str_replace('-', '', $ISBN13)); // この操作で、もともとハイフンがない場合もデータ型は文字列になる?
    if (strlen($ISBN13) === 13) {
        $nine = substr($ISBN13, 3, 9);
        $ISBN10 = $nine . ChkDgt10($nine);
        return $ISBN10;
    } else {
        return FALSE;
    }
}

// ISBN10 ⇒ ISBN13 に変換
function Isbn10213($ISBN10) {
    /* ※ 強制的に接頭記号を 978 としている。たぶん、979 の ISBN10 は(上記のコメントにより)存在しない筈?
    */

    $ISBN10 = trim(str_replace('-', '', $ISBN10)); // この操作で、もともとハイフンがない場合もデータ型は文字列になる?
    if (strlen($ISBN10) === 10) {
        $twelve = '978' . substr($ISBN10, 0, 9);
        $ISBN13 = $twelve . ChkDgt13($twelve);
        return $ISBN13;
    } else {
        return FALSE;
    }
}

/*******************************************************/

$Chk = '';
$Str = '';

// 入力値を元に変換
if (isset($_GET['Chk']) && $_GET['Chk']) {
    $Chk = trim(str_replace('-', '', $_GET['Chk']));
    if (strlen($Chk) === 10) {
        $Str .= 'ISBN10 : ' . $Chk . '<br />';
        $Str .= 'ISBN13 : ' . Isbn10213($Chk) . '<br />';
    }
    elseif (strlen($Chk) === 13) {
        $Str .= 'ISBN10 : ' . Isbn13210($Chk) . '<br />';
        $Str .= 'ISBN13 : ' . $Chk . '<br />';
    }
}

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<title>ISBN 10 ⇔ 13 変換</title>

</head>
<body>
<h1>ISBN 10 ⇔ 13 変換</h1>

<form action="" method="GET">
    <input type="text" id="Chk" name="Chk" value="<?php echo $Chk; ?>" />
    <input type="submit" value="変換" />
</form>

<p><?php echo $Str; ?></p>

</body>
</html>

Tail-Lagoon @ 13:07

コメントおよびトラックバック受付中です。
TB : http://weblogs.tail-lagoon.com/WebPC/2008/07/09/43/trackback/

コメントをどうぞ

この投稿へのコメントは RSS 2.0 フィードで購読できます。