Checksums - ISBN program

8.3k views Asked by At

This problem has me puzzled. I tried using a loop like this: Basically I tried to get the first digit from the input and do the formula but it doesn't seem to work. It looks so simple but I can't figure it out. Could you help me? Thanks.

public static int ISBN(String ninedigitNum) {
   number = 9;
   while (number > 0) {
   int nextDigit = ninedigitNum.substring(0,1);

   ...
}

Checksums (Source: Princeton University). The International Standard Book Number (ISBN) is a 10 digit code that uniquely specifies a book. The rightmost digit is a checksum digit which can be uniquely determined from the other 9 digits from the condition that d1 + 2d2 + 3d3 + ... + 10d10 must be a multiple of 11 (here di denotes the ith digit from the right). The checksum digit d1 can be any value from 0 to 10: the ISBN convention is to use the value X to denote 10. Example: the checksum digit corresponding to 020131452 is 5 since is the only value of d1 between 0 and and 10 for which d1 + 2*2 + 3*5 + 4*4 + 5*1 + 6*3 + 7*1 + 8*0 + 9*2 + 10*0 is a multiple of 11. Create a Java method ISBN() that takes a 9-digit integer as input, computes the checksum, and returns the 10-digit ISBN number. Create 3 JUnit test cases to test your method.

I got it, thanks a lot everyone!

4

There are 4 answers

4
AaronB On BEST ANSWER

What about it isn't working? Either way, I believe what you're missing is that you're continually getting the same substring, which will be the first number of the string: int nextDigit = ninedigitNum.substring(0,1);. In addition, you're going to want to use an int, not a String; you can technically convert from String to int if desired, but the problem itself calls for an int.

There are two ways to do this that jump to mind. I would do this by realizing that mod in powers of 10 will give you the respective digit of an integer, but the easier way is to convert to a char array and then access directly. Note that there's no error checking here; you'll have to add that yourself. In addition, there are a LOT of 'magic numbers' here: good code typically has very, very few. I would recommend learning more data structures before attempting problems like these; to be honest there's very few things you can do without at least arrays and linked lists.

char[] ISBN = ninedigitNum.toCharArray();

//Process each number
int total = 0;
for(int i=0; i<9; i++){
    int current_int = Integer.parseInt(ISBN[i]);
    total += current_int * (10 - i)
}

//Find value of d1
for(int i=0; i<9; i++){
    if(((total + i) % 11) == 0){
        total += i*100000000;
        break;
    }
}

return total;

In general: Use print outs with System.out.println(x); or use your compiler's debugger to see what's going on during processing.

0
Sameer Sawla On

So, This is the piece of code that I wrote. I still think it could be made more efficient.

public class Problem3 {
    public static String ISBN(String x)
    {
       char[]temp = x.toCharArray();
       int counter = 2;
       int sum = 0;
       int j=0;
       for(int i=8;i>=0;i--)
       {
           sum+= counter*Integer.parseInt(""+temp[i]);
           counter+=1;
       }
       for(j=0;j<10;j++)
       {
           if((sum+j)%11==0)
           {
               break;
           }
       }
       return x+""+j;
    }
public static void main(String args[])    
{
   String a = "020131452"; 
   System.out.println(ISBN(a));

}
}

Hope this helps.

0
ThaBomb On

This works:

public static int ISBN(String nineDigitNum){
    int sum = 0;
    for(int i = 0; i<nineDigitNum.length(); i++){
        sum += Integer.parseInt(""+nineDigitNum.charAt(i))*(10-i);
    }
    return (sum%11);
}

Also I believe if the checksum is == to 10, it should return an X, so you could either change the return type and add an if statement somewhere, or just put the if statement outside wherever you are using this method.

0
dansalmo On

Here is a short one without loops that uses only substring(), charAt() and length():

public static String ISBN(String nineDigits) {
    int chkD = 11 - checkDigit(nineDigits, 0);
    return nineDigits + ((chkD == 10) ? "X" : chkD);
}

public static int checkDigit(String nDsub, int chkD) {
    if (nDsub.length() == 0)
        return 0;
    chkD = ((nDsub.charAt(0) - '0') * (nDsub.length() + 1));
    return (chkD + checkDigit(nDsub.substring(1), chkD)) % 11;
}

Output:

> ISBN("123456789")
"123456789X"
> ISBN("123456780")
"1234567806"