For a project I needed to validate a 13 digit ISBN. According to Wikipedia you can validate an ISBN by calculating the checksum, but more accurately calculating the check-digit of an ISBN as follows:

The ISBN-13 check digit, which is the last digit of the ISBN, must range from 0 to 9 and must be such that the sum of all the thirteen digits, each multiplied by its (integer) weight, alternating between 1 and 3, is a multiple of 10.

In other words, if your ISBN is 978-0-141-98376-9, you’d do this:

1*9 + 3*7 + 1*8 + 3*0 + 1*1 + 3*4 + 1*1 + 3*9 + 1*8 + 3*3 + 1*7 + 3*6 + 1*9 = 130

If you divide 130 by 10 you get a straight 13, no remainder and you are golden (in other words 130 % 10 = 0). However there are some complications and I trust the good guys at Wikipedia to have gotten it right and thus let us validate the last digit of the ISBN (i.e. 9).

We do the same math as above, except that we skip the last digit, after all it is our check-digit:

1*9 + 3*7 + 1*8 + 3*0 + 1*1 + 3*4 + 1*1 + 3*9 + 1*8 + 3*3 + 1*7 + 3*6 = 121

You’ll remember from a math lesson long ago, 121 % 10 = 1

10 – 1 = 9

In our function we’ll use another modulus of 10, just for those odd times our check digit is 0 as in those cases our check sum would have a 0 remainder on the modulus operation, but 10 – 0 = 10 and 0 – 10 != 0, however if 10 – 0 is 10 the modulus of 10 of 10 is 0 an then 0 – 0 == 0 and that’s true. I am confusing myself here, so I am likely confusing you…

In a Swift Function, you could express this as follows:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
func validISBN13(isbn: String) -> Bool{ let weight = [1, 3] var checksum = 0 for i in 0..<12 { if let intCharacter = Int(String(isbn[isbn.index(isbn.startIndex, offsetBy: i)])) { checksum += weight[i % 2] * intCharacter } } if let checkDigit = Int(String(isbn[isbn.index(isbn.startIndex, offsetBy: 12)])) { return (checkDigit - ((10 - (checksum % 10)) % 10) == 0) } return false } |