Jay da science noob Jay da science noob - 1 month ago 6
Java Question

Return 'X' when sum of 9 digits divided by 11 is 10

In my code, I want

charSum
to return
'X'
if the remainder is 10 when the sum of 9 digits is divided by 9. I tried both
charSum = 'X'
and
charSum = (char) 88
and neither works. Something in my algorithm must be wrong. Please help.

public static char getCheckSum(String isbn) {
int sum = 0;

for (int i = 0; i < isbn.length(); i++) {
int[] num = new int[isbn.length()];
num[i] = Character.getNumericValue(isbn.charAt(i));
sum = sum + num[i];
}
int last = (sum % 11);
char charSum;
if (last == 10){
charSum = 'X';
} else {
charSum = (char) (last + 48);
}
return charSum;
}

public static String formatISBNWithHyphens(String isbn) {
// original isbn: 123456789
// possible new isbn: 1-234-56789-X
char isbn10 = getCheckSum(isbn);
String isbn10Str = isbn + Character.toString(isbn10);

// char[] c = new char[isbn10Str.length()]; *leaving this here for future learning.
String[] cStr = new String[isbn10Str.length()];
String isbnStr = "";
for (int i = 0; i < isbn10Str.length(); i++){
cStr[i] = Character.toString(isbn10Str.charAt(i));
// c[i] = isbn10Str.charAt(i); *leaving this here for future learning.
if (i == 0 || i == 3 || i == 8 ) {
cStr[i] += '-';
}

isbnStr += cStr[i];
}
return isbnStr;
}

Answer

It works fine. If I run it with 933456789 (the sum of which is 54, so 54 % 11 = 10), the getCheckSum() method returns X as expected.

However, this does not seem like the correct way to calculate an ISBN-10 checksum. According to Wikipedia:

The 2001 edition of the official manual of the International ISBN Agency says that the ISBN-10 check digit – which is the last digit of the ten-digit ISBN – must range from 0 to 10 (the symbol X is used for 10), and must be such that the sum of all the ten digits, each multiplied by its (integer) weight, descending from 10 to 1, is a multiple of 11.

I've implemented it according to the specification as follows:

public static char getCheckDigit(String isbn) {
    if (isbn == null || !isbn.matches("[0-9]{9,}")) {
        throw new IllegalArgumentException("Illegal ISBN value");
    }

    int sum = 0;

    for (int i = 0; i < 9; i++) {
        sum += ((10 - i) * Character.digit(isbn.charAt(i), 10));
    }

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

    return check == 10 ? 'X' : Character.forDigit(check, 10);
}

Applied to a couple of ISBN values I found on the same Wikipedia page:

getCheckDigit("097522980"); // --> returns 'X'
getCheckDigit("094339604"); // --> returns '2'
getCheckDigit("999215810"); // --> returns '7'
Comments