ASP.NET Hosting

ISBN-13 to ISBN-10

If for some reason you need to convert an ISBN-13 to ISBN-10 (one being that Amazon doesn't support ISBN-13 in product affiliate links) then you need not only to remove the first three characters. You also need to recompute the checksum.

Here is a piece of code that I wrote to handle this conversion:

public static String Isbn13to10(String isbn13)
{
  if (String.IsNullOrEmpty(isbn13))
    throw new ArgumentNullException("isbn13");
  isbn13 = isbn13.Replace("-", "").Replace(" ", "");
  if (isbn13.Length != 13)
    throw new ArgumentException("The ISBN doesn't contain 13 characters.", "isbn13");

  String isbn10 = isbn13.Substring(3, 9);
  int checksum = 0;
  int weight = 10;

  foreach (Char c in isbn10)
  {
    checksum += (int)Char.GetNumericValue(c) * weight;
    weight--;
  }

  checksum = 11-(checksum % 11);
  if (checksum == 10)
    isbn10 += "X";
  else if (checksum == 11)
    isbn10 += "0";
  else
    isbn10 += checksum;

  return isbn10;
}


I use this to create the Amazon affiliate links on Clair de Bulle, the famous French comics website of my wife. Yes, it's the holidays season, so I have to work for her ;-)

15 Comments

  • Thanks for this! I translated it into Ruby if anyone's interested:



    def isbn_13_to_isbn_10(isbn13)
    isbn10 = isbn13[3,9]
    checksum = 0
    weight = 10
    isbn10.each_char do |c|
    checksum += (c.to_i * weight)
    weight -= 1
    end
    checksum = 11-(checksum % 11)
    if (checksum == 10)
    isbn10 += "X"
    elsif (checksum == 11)
    isbn10 += "0"
    else
    isbn10 += checksum.to_s
    end
    isbn10
    end

  • This is just what I was looking for, well sort of. I need to translate it into VBA for an Excel form. I came up with the following, but it keeps throwing errors...
    'The ISBN-10 equals the ISBN 13 between the 4th and penultimate characters
    isbn10 = OrigISBN.Substring(3, 9)
    'Declare the starting values

    checksum = 0
    Weight = 10

    'Loop through ISBN-10 adjusting checksum for each character, in order to recalculate the check digit
    For i = 1 To 10
    checksum = checksum + ((Mid(isbn10, i, 1)) * Weight)
    Weight = Weight - 1
    Next i

    checksum = 11 - (checksum Mod 11)
    If checksum = 10 Then
    isbn10 = isbn10 & "X"
    ElseIf checksum = 11 Then
    isbn10 = isbn10 & "0"
    Else: isbn10 = isbn10 & checksum
    End If
    isbn10TextBox.Text = isbn10


    End Sub

  • Hi,

    there is an error on the algo at this line :

    String myIsbn10 = theIsbn13.substring(3, 9);

    Indeed, the second number must be 12 instead of 9 : You have to remove only the first 3 numbers and the last digit from the isbn-13.

    Thanks for all.

  • Another comment to complete this function. It read that ISBN-13 starting with 979 can't be converted into ISBN-10. So add into the function a line to check if the ISBN-13 we have to convert start with "979" and threw an exception if it is the case :

    // --- Check if current ISBN-13 not start with 979
    // ---(can't be converted to ISBN-10)
    if ( theIsbn13.startsWith("979") )
    throw new EngineException("Can't format isbn 13 to 10 starting with 979");

    The function should be now complete.

  • Thanks!

    Here is a visual basic version that works fine:

    Public Function Isbn13to10(isbn13 As String) As String


    isbn10 = Mid(isbn13, 4, 9)
    Dim checksum
    checksum = 0
    Dim weight
    weight = 10

    For i = 1 To Len(isbn10)
    checksum = checksum + ((Mid(isbn10, i, 1)) * weight)

    weight = weight - 1

    Next i

    checksum = 11 - (checksum Mod 11)

    If checksum = 10 Then
    isbn10 = isbn10 & "X"
    Else
    If checksum = 11 Then
    isbn10 = isbn10 & "0"
    Else
    isbn10 = isbn10 & checksum
    End If
    End If

    Isbn13to10 = isbn10

    End Function

  • Ok, sorry for flooding this page, but again, ignore the previous code. I promise you, this is the last time (because I've now perfected my code, and removed all bugs).

    Option Strict On
    Option Explicit On
    Module Module1

    Dim sISBN13 As String = ""
    Dim sISBN10 As String = ""

    Function bVerifySum13(ByRef usISBN13 As String) As Boolean
    Dim iMax, iSum As Integer
    bVerifySum13 = True
    iMax = 0
    If usISBN13 Like "#############" Then
    For j As Integer = 2 To 12 Step 2
    iMax += ((Convert.ToInt32(Mid(usISBN13, (j - 1), 1))) + (3 * (Convert.ToInt32(Mid(usISBN13, j, 1)))))
    Next
    iSum = (10 - (iMax Mod 10)) Mod 10
    If iSum Convert.ToInt32(Mid(usISBN13, 13, 1)) Then
    bVerifySum13 = False
    End If
    Else
    bVerifySum13 = False
    End If
    End Function

    Function bVerifySum10(ByRef usISBN10 As String) As Boolean
    Dim iMax As Integer = 0
    bVerifySum10 = True
    If usISBN10 Like "##########" Or usISBN10.Length = 10 And Mid(usISBN10, 1, 9) Like "#########" And Mid(usISBN10, 10, 1) = "x" Then
    For j = 10 To 2 Step -1
    iMax += ((Convert.ToInt32(Mid(usISBN10, (10 - (j - 1)), 1))) * j)
    Next
    If Mid(usISBN10, 10, 1) "x" Then
    iMax += Convert.ToInt32(Mid(usISBN10, 10, 1))
    Else
    iMax += 10
    End If
    If (iMax Mod 11) 0 Then
    bVerifySum10 = False
    End If
    Else
    bVerifySum10 = False
    End If
    End Function

    Function sConvertN10toN13(ByRef usISBN10 As String) As String
    Dim iMax As Integer = 0
    sConvertN10toN13 = "978" + Mid(usISBN10, 1, 9)
    For j As Integer = 2 To 12 Step 2
    iMax += (Convert.ToInt32(Mid(sConvertN10toN13, (j - 1), 1))) + (3 * (Convert.ToInt32(Mid(sConvertN10toN13, j, 1))))
    Next
    sConvertN10toN13 += ((10 - (iMax Mod 10)) Mod 10).ToString
    End Function

    Function sConvertN13toN10(ByRef usISBN13 As String) As String
    Dim iMax As Integer = 0
    Dim iCount As Integer = 0
    sConvertN13toN10 = Mid(usISBN13, 4, 9)
    For j As Integer = 10 To 2 Step -1
    iMax += ((Convert.ToInt32(Mid(sConvertN13toN10, (10 - (j - 1)), 1))) * j)
    Next
    If (iMax Mod 11) 0 Then
    Do
    iCount += 1
    Loop Until ((iMax + iCount) Mod 11) = 0
    If iCount = 10 Then
    sConvertN13toN10 += "x"
    Else
    sConvertN13toN10 += iCount.ToString
    End If
    Else
    sConvertN13toN10 += "0"
    End If
    End Function

    Sub Main()
    Dim sInputChoice As String = ""
    Call shameless_plug()
    Call DisplayOptions()
    Do
    Call Console.Write("?: ")
    sInputChoice = Console.ReadLine()
    Select Case sInputChoice
    Case "quit"
    End
    Case "disp"
    Call DisplayOptions()
    Case "10"
    Call InterfaceISBN10()
    Case "13"
    Call InterfaceISBN13()
    Case "10to13"
    Call InterfaceISBN10ToISBN13()
    Case "13to10"
    Call InterfaceISBN13ToISBN10()
    Case Else
    Call Console.WriteLine("Invalid option")
    End Select
    Loop
    End Sub

    Sub InterfaceISBN10()
    Call Console.WriteLine()
    Call Console.WriteLine("ISBN-10 Validation")
    Call Console.WriteLine("(To exit back to main menu, type 'r' and hit return)")
    Do Until sISBN10 = "r"
    Call Console.Write("?10: ")
    sISBN10 = Console.ReadLine()
    sISBN10 = sISBN10.ToLower
    If sISBN10 "r" And bVerifySum10(sISBN10) True Then
    Call Console.WriteLine("Invalid ISBN-10 number")
    ElseIf sISBN10 "r" And bVerifySum10(sISBN10) = True Then
    Call Console.WriteLine("Valid ISBN-10 number")
    End If
    Loop
    Call Console.WriteLine()
    Call DisplayOptions()
    End Sub

    Sub InterfaceISBN13()
    Call Console.WriteLine()
    Call Console.WriteLine("ISBN-13 Validation")
    Call Console.WriteLine("(To exit back to main menu, type 'r' and hit return)")
    Do Until sISBN13 = "r"
    Call Console.Write("?13: ")
    sISBN13 = Console.ReadLine()
    sISBN13 = sISBN13.ToLower
    If sISBN13 "r" And bVerifySum13(sISBN13) True Then
    Call Console.WriteLine("Invalid ISBN-13 number")
    ElseIf sISBN13 "r" And bVerifySum13(sISBN13) = True Then
    Call Console.WriteLine("Valid ISBN-13 number")
    End If
    Loop
    Call Console.WriteLine()
    Call DisplayOptions()
    End Sub

    Sub InterfaceISBN10ToISBN13()
    Call Console.WriteLine()
    Call Console.WriteLine("ISBN10 to ISBN13 conversion")
    Call Console.WriteLine("(To exit back to the main menu, type 'r' and hit return)")
    Do
    Call Console.Write("?10: ")
    sISBN10 = Console.ReadLine()
    sISBN10 = sISBN10.ToLower
    If sISBN10 "r" And bVerifySum10(sISBN10) True Then
    Call Console.WriteLine("Invalid input")
    ElseIf sISBN10 "r" And bVerifySum10(sISBN10) = True Then
    Call Console.WriteLine("As an ISBN13 number, this is " + sConvertN10toN13(sISBN10))
    Call System.Threading.Thread.Sleep(1200)
    Call Console.WriteLine("Verification of newly converted ISBN13 number...")
    Call System.Threading.Thread.Sleep(300)
    If bVerifySum13(sConvertN10toN13(sISBN10)) True Then
    Call Console.WriteLine("Oops, it seems that this is invalid")
    Else
    Call Console.WriteLine("Everything A-OK")
    End If
    End If
    Loop Until sISBN10 = "r"
    Call Console.WriteLine()
    Call DisplayOptions()
    End Sub

    Sub InterfaceISBN13ToISBN10()
    Call Console.WriteLine()
    Call Console.WriteLine("ISBN13 to ISBN10 conversion")
    Call Console.WriteLine("(To exit back to the main menu, type 'r' and hit return)")
    Do
    Call Console.Write("?13: ")
    sISBN13 = Console.ReadLine()
    sISBN13 = sISBN13.ToLower
    If sISBN13 "r" And bVerifySum13(sISBN13) True Then
    Call Console.WriteLine("Invalid input")
    ElseIf sISBN13 "r" And bVerifySum13(sISBN13) = True Then
    Call Console.WriteLine("As an ISBN10 number, this is " + sConvertN13toN10(sISBN13))
    Call System.Threading.Thread.Sleep(1200)
    Call Console.WriteLine("Verification of newly converted ISBN10 number...")
    Call System.Threading.Thread.Sleep(300)
    If bVerifySum10(sConvertN13toN10(sISBN13)) True Then
    Call Console.WriteLine("Oops, it seems that this is invalid")
    Else
    Call Console.WriteLine("Everything A-OK")
    End If
    End If
    Loop Until sISBN13 = "r"
    Call Console.WriteLine()
    Call DisplayOptions()
    End Sub

    Sub DisplayOptions()
    Call Console.WriteLine("Options:")
    Call Console.WriteLine("10 - ISBN10 validation")
    Call Console.WriteLine("13 - ISBN13 validation")
    Call Console.WriteLine("10to13 - ISBN10 to ISBN13 conversion")
    Call Console.WriteLine("13to10 - ISBN13 to ISBN10 conversion")
    Call Console.WriteLine("disp - display these options")
    Call Console.WriteLine("quit - exit this program")
    End Sub

    Sub shameless_plug()
    Call Console.WriteLine("Z-130 version pi")
    Call Console.WriteLine("Written by Zero-Hero")
    Call Console.WriteLine("License: Public Domain")
    Call Console.WriteLine()
    Call Console.WriteLine("This program does the following:")
    Call Console.WriteLine("1) Convert (either way) between ISBN10 and ISBN13, at your choice")
    Call Console.WriteLine("2) Check the validity of either an ISBN10 or ISBN13 number, at your choice")
    Call Console.WriteLine()
    Call Console.WriteLine("This program will NOT do the following:")
    Call Console.WriteLine("1) Make girls like you")
    Call Console.WriteLine("2) Make men like you")
    Call Console.WriteLine()
    Call Console.Write("Press enter to continue")
    Call Console.ReadLine()
    Call Console.WriteLine()
    End Sub

    End Module

  • There is a slight error in the code, which will cause problems for ISBNs with Xs on the end.

    In the PHP on about Line 13

    $isbn10 += "X";

    Should be something like

    $isbn10 = $isbn10 . "X";

    Because PHP appends with '.' not '+'.

    The line below that also looks suspicious, the one with the 0, although I haven't had any problems caused by it, I'm going to change it in my code.

    Anyway, if anyone is having strange errors, hopefully the function below will help solve it:

    function isbn13_to_isbn10($isbn13) {
    $isbn13 = trim($isbn13);
    $isbn13 = str_replace("-","",$isbn13);
    $isbn13 = str_replace(" ","",$isbn13);
    $isbn10 = substr($isbn13,3,9);
    $checksum = 0;
    $weight = 10;
    $isbnCharArray = str_split($isbn10);
    foreach($isbnCharArray as $char) {
    $checksum += $char * $weight;
    $weight--;
    }
    $checksum = 11-($checksum % 11);
    if ($checksum == 10) { $isbn10 = $isbn10 . "X"; }
    else if ($checksum == 11) { $isbn10 += "0k"; }
    else $isbn10 .= $checksum;
    return $isbn10;
    }

  • Thanks for the code examples.

    Actually Amazon does support ISBN-13, but tagged as EAN (if you parse AWS XML response).
    And ISBN still means ISBN-10.

  • can someone post the VB net function to convert from ISBN 10 TO 13 instead?

    thanks.

  • Thank you... this is what we're looking for.....

  • Hey Guys,

    Great work. The comment Philip Kimmey is really useful and a very important modification. I had the problem with that kind of ISBN-13 number. Now it is solved. Thanks to Philip Kimmey.

    Cheers.

  • SQL Server UDF (User Defined Function)


    /*
    Description: Converts a 13 digit ISBN to a 10 digit ISBN

    */
    CREATE FUNCTION [dbo].[ConvertISBN13_To_10](@in_ISBN VARCHAR(20))

    RETURNS VARCHAR(20)

    AS


    BEGIN

    --VARS
    DECLARE @wf INT; SET @wf = 10;
    DECLARE @CurrentDigit INT; SET @CurrentDigit = 1;
    DECLARE @iTotal INT; SET @iTotal = 0;
    DECLARE @IsbnDigit INT; SET @IsbnDigit = 0;
    DECLARE @Leftover INT; SET @Leftover = 0;
    DECLARE @ISBN10_NoChk VARCHAR(9)
    DECLARE @ISBN10 VARCHAR(20)
    DECLARE @Error BIT; SET @Error = 0;

    --make sure it's a 978 13 digit ISBN, if not, just return what was passed in
    IF(LEN(@in_ISBN) = 13 AND SUBSTRING(@in_ISBN, 1, 3) = '978')
    BEGIN
    --drop the ISBN13 check digit and prefix
    SET @ISBN10_NoChk = SUBSTRING(@in_ISBN, 4, 9)

    --loop to find the conversion sum
    WHILE (@CurrentDigit < 10 AND @Error = 0)
    BEGIN
    --get the current digit (make sure it's numeric)
    IF(CAST(SUBSTRING(@ISBN10_NoChk, @CurrentDigit, 1) AS VARBINARY) between 0x30 and 0x39)
    BEGIN
    SET @IsbnDigit = CAST(SUBSTRING(@ISBN10_NoChk, @CurrentDigit, 1) AS INT)

    --add the weighted value to the conversion sum
    SET @iTotal = @iTotal + (@IsbnDigit * (@wf - @CurrentDigit + 1));


    --move to the next digit in the ISBN
    SET @CurrentDigit = @CurrentDigit + 1
    END
    ELSE --found an alpha, cancel conversion
    BEGIN
    SET @Error = 1
    SET @ISBN10 = @in_ISBN
    END
    END

    --if no error, find the mod (remainder) for the conversion
    IF(@Error = 0)
    BEGIN
    --get the leftover
    SET @Leftover = @iTotal % 11;

    --Create ISBN13 (if check digit = 10 convert to '0')
    IF(@Leftover = 0)
    SET @ISBN10 = @ISBN10_NoChk + '0'
    ELSE
    BEGIN
    IF((11 - @Leftover) = 10)
    SET @ISBN10 = @ISBN10_NoChk + 'X'
    ELSE
    SET @ISBN10 = @ISBN10_NoChk + CAST((11 - @Leftover) AS VARCHAR(2))
    END
    END
    END
    ELSE --Bad ISBN, cancel conversion
    BEGIN
    SET @ISBN10 = @in_ISBN
    END

    --output results
    RETURN @ISBN10

    END

    GO

  • When I run the PHP version and the ISBN-10 number ends in zero the zero is removed and it becomes a 9 digit #. I'm not a programmer so I'm unable to figure out what is wrong.

  • any updates on the following?

    When I run the PHP version and the ISBN-10 number ends in zero the zero is removed and it becomes a 9 digit #. I'm not a programmer so I'm unable to figure out what is wrong.

  • this was the fix for php. it was that 'k' next to the '0':

    //$isbn10 += "0k";

    $isbn10 .= "0";

Comments have been disabled for this content.