【问题标题】:is this ISBN-10 Checksum calculation in php correct?php 中的 ISBN-10 校验和计算是否正确?
【发布时间】:2018-07-20 08:14:38
【问题描述】:

我找到了一个 PHP 脚本github ISBN-Calc Routine 来执行 ISBN-10 校验和计算:

<?php
/**
 * Calculate ISBN checksum
 * 
 * @param string $isbn
 * @return integer
 */
function isbn_checksum($isbn) {
    $sum = 0; $isbn = str_split(preg_replace('/[^\d]/', '', $isbn));
    foreach($isbn as $key => $z) {
        if($key >= 12) break;
        $sum += ($key % 2) ? $z * 3 : $z;
    }
    $checksum = (10 - $sum % 10);
    return ($checksum == 10) ? 0 : $checksum;
}

但是对于我的ISBN-10: 0470173424,我通过这个 github 脚本得到了Checksum: 0

根据ISBN online checker,校验​​和应该是 4,就像 ISBN 中一样。请问这里有人可以提供正确的PHP例程吗?

谢谢

【问题讨论】:

  • 您尝试过什么调试?如果脚本没有按预期工作,请选择另一个 - 算法非常简单

标签: php isbn


【解决方案1】:

该函数用于计算 ISBN-13 校验位,而不是 ISBN-10 - 这就是它在第 12 个字符后中断循环的原因。

ISBN-10 的算法不同,它需要将数字的前 9 位数字乘以 10 直到 2。该总和与下一个 11 的倍数之间的差是校验位。对于您的示例,这将是:

(10 * 0) + (9 * 4) + (8 * 7) + (7 * 0) + (6 * 1) + (5 * 7) + (4 * 3) + (3 * 4) + (2 * 2) = 161

11 的下一个倍数是 165,所以校验位应该是 4(如你所说)。在校验位为 10 的情况下,使用 X。我们可以像这样在 PHP 中建模:

function isbn10($isbn) {
    $isbn = preg_replace('/[^\d]/', '', $isbn);
    $digits = str_split(substr($isbn, 0, 9));

    $sum = 0;

    foreach ($digits as $index => $digit) {
        $sum += (10 - $index) * $digit;
    }

    $check = 11 - ($sum % 11);

    return ($check === 10) ? 'X' : $check;
}

echo isbn10('047017342');

4

你可以在这里看到这个工作:https://eval.in/1039654

【讨论】:

    【解决方案2】:

    之前标记的答案很接近但不完整。

    特别是这部分:

    $check = 11 - ($sum % 11); // This can output 1,2,3,4,5,6,7,8,9,10,11 not 0
    return ($check === 10) ? 'X' : $check; // This is incomplete does not address 11
    

    代码没有处理11 - 0 = 11的情况。我试图在下面澄清一下。

    function isbn10($isbn)
    {
      $isbn = preg_replace('/[^\d]/', '', $isbn);
      $digits = str_split(substr($isbn, 0, 9));
    
      $sum = 0;
    
      foreach ($digits as $index => $digit)
      {
          $sum += (10 - $index) * $digit;
      }
    
      $check = 11 - ($sum % 11);
    
      // $check may hold either 10 or 11, but not 0
      // 10 becomes X, 11 becomes 0 -- output is 1 character only
      if ($check == 10)
      {
        $check = 'X';
      }
      elseif ($check == 11)
      {
        $check = '0';
      }
    
      return $check;
    }
    

    较早答案失败的示例 ISBN 是 0134093410

    【讨论】:

      【解决方案3】:

      GitHub有一个库:https://github.com/Fale/isbn

      有一个函数叫做“检查”

      初始化:

      $isbn = new Isbn\Isbn();
      

      检查值:(示例)

      $isbn->check->is10('888183718'); // Will return false
      $isbn->check->is13('9788889527191'); // Will return true
      $isbn->check->is13('978888952719'); // Will return false
      

      您可以从给定的链接下载库。

      也许这有点帮助。

      周末愉快!

      【讨论】:

        【解决方案4】:

        如果要检查 ISBN-10 是否正确

        验证 ISBN-10

        <?php
        function isValidIsbn10($isbn) {
            $check = 0;
            for ($i = 0; $i < 10; $i++) {
                if ('x' === strtolower($isbn[$i])) {
                    $check += 10 * (10 - $i);
                } elseif (is_numeric($isbn[$i])) {
                    $check += (int)$isbn[$i] * (10 - $i);
                } else {
                    return false;
                }
            }
            return (0 === ($check % 11)) ? 1 : false;
        }
        
        var_dump( isValidIsbn10('0470173424') );
        

        来源:https://stackoverflow.com/a/14096142/5201919

        将显示

        1 为真

        演示

        https://eval.in/1053913

        【讨论】:

        • 你从某个地方复制了这个,引用你的来源。
        猜你喜欢
        • 2012-09-03
        • 1970-01-01
        • 1970-01-01
        • 2016-05-31
        • 1970-01-01
        • 2015-04-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多