0

I have found a PHP script github ISBN-Calc Routine to perform the ISBN-10 checksum calculation:

<?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;
}

But f.e for my ISBN-10: 0470173424 I get Checksum: 0with this github script.

Accoring to ISBN online checker the checksum should be 4 as is it in the ISBN. Can anyone here provide me with the correct PHP routine, please?

Thanks

adilbo
  • 910
  • 14
  • 22
Walter Schrabmair
  • 1,251
  • 2
  • 13
  • 26
  • What have you tried to debug this? If the script does not work as expected, choose another - the algorithm is pretty simple – Nico Haase Jul 20 '18 at 08:34

4 Answers4

2

That function is for calculating an ISBN-13 check digit, not ISBN-10 - that's why it breaks the loop after the 12th character.

The algorithm for ISBN-10 is different, and requires multiplying the first 9 digits of the number by 10 down to 2. The difference between that sum and the next multiple of 11 is the check-digit. For your example, this would be:

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

The next multiple of 11 is 165, so the check-digit should be 4 (as you say). In the case where the check-digit would be 10, X is used. We can model this in PHP like this:

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

You can see this working here: https://eval.in/1039654

iainn
  • 16,826
  • 9
  • 33
  • 40
1

The previously marked answer is close but incomplete.

Specifically this portion:

$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

The code does not deal with the situation where 11 - 0 = 11. I have tried to clarify it below.

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;
}

An example ISBN where the earlier answer fails is 0134093410

Morgan
  • 26
  • 1
-1

There is an library from GitHub: https://github.com/Fale/isbn

There is a function called "Check":

Initialization:

$isbn = new Isbn\Isbn();

Check values: (Example)

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

You can download the library from the given link.

Maybe that helps a bit.

Have a nice weekend!

MrzJkl
  • 173
  • 1
  • 9
-1

If you want to check if the ISBN-10 is correct

Validate 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') );

Source: https://stackoverflow.com/a/14096142/5201919

Will show

1 for true

Demo

https://eval.in/1053913

adilbo
  • 910
  • 14
  • 22