Jekyll2021-01-05T04:39:11+03:00https://dtsvikevich.ru/blog/feed.xmlDenis Tsvikevich’s BlogWelcome to my personal blog about IT, web and others topics!Denis Tsvikevichdtsvikevich@gmail.comISBN check digit calculation2020-11-30T00:00:00+03:002020-11-30T00:00:00+03:00https://dtsvikevich.ru/blog/2020/11/isbn-check-digit<p>Today we will learn how to calculate SBN, ISBN-10 & ISBN-13 check digit and write these algorithms in JavaScript</p>
<h2 id="introduction">Introduction</h2>
<p><strong>ISBN (International Standard Book Number)</strong> is a unique numeric book identifier, required for the distribution of the book in retail chains and automation of work with the publication.</p>
<p>ISBN based upon 9-digit <strong>SBN (Standard Book Number)</strong> created in 1965. There are two types of
ISBN. First, called <strong>ISBN-10</strong> (10 means 10-digit) is also deprecated format, developed by ISO was published in 1970. ISBN-10 consists of four parts:</p>
<p><img src="/blog/assets/images/isbn-1.svg" alt="ISBN-10 structrue" title="ISBN-10 structrue" /></p>
<p>The most interesting part for us is the last - check digit. A <strong>check digit</strong> is a form of redundancy check used for error detection on identification numbers. It should be noted here that the last digit can be the letter X, which represents the value 10.</p>
<p>Currently active (since 2007) standart, <strong>ISBN-13</strong>, is looks very similar to ISBN-10. The difference is that ISBN-13 also have <a href="https://en.wikipedia.org/wiki/International_Article_Number">EAN prefix</a> (always 978 or 979) and check digit can not be a letter X.</p>
<p><img src="/blog/assets/images/isbn-2.svg" alt="ISBN-13 structrue" title="ISBN-13 structrue" /></p>
<p>To learn more about ISBN you can <a href="https://www.isbn-international.org/">visit International ISBN Agency site</a>. There is a comparison table of ISBN formats:</p>
<table>
<thead>
<tr>
<th>Standart</th>
<th>Length</th>
<th>EAN prefix</th>
<th>X as check digit</th>
</tr>
</thead>
<tbody>
<tr>
<td>SBN</td>
<td>9</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>ISBN-10</td>
<td>10</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>ISBN-13</td>
<td>13</td>
<td>Yes</td>
<td>No</td>
</tr>
</tbody>
</table>
<p>It is possible to convert SBN to ISBN-10: just add prefix 0 to SBN:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SBN: 12345678-9
ISBN-10: 012345678-9
</code></pre></div></div>
<p>Also you can convert ISBN-10 to ISBN-13 by adding prefix 978 and <strong>recalculating check digit</strong>:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ISBN-10: 012345678-9
ISBN-13: 978-012345678-6
</code></pre></div></div>
<p><img src="/blog/assets/images/isbn-conversion-scheme.svg" alt="ISBN coversion scheme" title="ISBN coversion scheme" /></p>
<h2 id="sbn-check-digit">SBN check digit</h2>
<p>To calculate SBN check digit you can convert SBN to ISBN-10 and calculate ISBN-10 check digit
(it will be the same as SBN check digit).</p>
<h2 id="isbn-10-check-digit">ISBN-10 check digit</h2>
<p>ISBN-10 check digit must range from 0 to 10 (X). To calculate ISBN-10 check digit you can use following
formula:</p>
<p class="formula">
@d_10=[11 - (sum_(i=1)^9 (11-i)*d_i) mod 11] mod 11@
</p>
<p>for example, lets eval check digit of ISBN-10 123-456-789-_:</p>
<p class="formula">
@d_10=[11 - (10 * 1 + 9 * 2 + 8 * 3 + 7 * 4 + 6 * 5 + 5 * 6 + 4 * 7 + 3 * 8 + 2 * 9) mod 11] mod 11@
@d_10=(11 - 210 mod 11) mod 11 = (11 - 1) mod 11 = 10@
</p>
<p>so check digit is X and ISBN-10 is 123-456-789-X.</p>
<p>JavaScript implementation:</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
* Converts ISBN string to digit array (X in ISBN-10 also supported)
*
* @param {string} isbn - ISBN string representation
* @returns {number[]} array of digits, converted to numbers
*/</span>
<span class="kd">function</span> <span class="nx">toIsbnDigits</span><span class="p">(</span><span class="nx">isbn</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">[...</span><span class="nx">isbn</span><span class="p">].</span><span class="nx">map</span><span class="p">(</span><span class="nx">char</span> <span class="o">=></span>
<span class="nx">char</span><span class="p">.</span><span class="nx">toLowerCase</span><span class="p">()</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">x</span><span class="dl">"</span> <span class="p">?</span> <span class="mi">10</span> <span class="p">:</span> <span class="nb">Number</span><span class="p">.</span><span class="nb">parseInt</span><span class="p">(</span><span class="nx">char</span><span class="p">));</span>
<span class="p">}</span>
<span class="cm">/**
* Calculates check digit of ISBN-10
*
* @param {number[]} digits - ISBN-10 digit array
* @returns {number} check digit of ISBN-10
*/</span>
<span class="kd">function</span> <span class="nx">checkDigitIsbn10</span><span class="p">(</span><span class="nx">digits</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="mi">9</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">sum</span> <span class="o">+=</span> <span class="p">(</span><span class="mi">10</span> <span class="o">-</span> <span class="nx">i</span><span class="p">)</span> <span class="o">*</span> <span class="nx">digits</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
<span class="p">}</span>
<span class="kd">let</span> <span class="nx">digit</span> <span class="o">=</span> <span class="p">(</span><span class="mi">11</span> <span class="o">-</span> <span class="p">(</span><span class="nx">sum</span> <span class="o">%</span> <span class="mi">11</span><span class="p">))</span> <span class="o">%</span> <span class="mi">11</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">digit</span> <span class="o">===</span> <span class="mi">10</span> <span class="p">?</span> <span class="dl">"</span><span class="s2">X</span><span class="dl">"</span> <span class="p">:</span> <span class="nx">digit</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">checkDigitIsbn10</span><span class="p">(</span><span class="nx">toIsbnDigits</span><span class="p">(</span><span class="dl">"</span><span class="s2">123456789</span><span class="dl">"</span><span class="p">)));</span> <span class="c1">//=> X</span>
</code></pre></div></div>
<h2 id="isbn-13-check-digit">ISBN-13 check digit</h2>
<p>Let</p>
<p class="formula">
@"alter"(x) = {(1, ;, odd),(3, ;, even):}@
</p>
<p>then ISBN-13 check digit equals</p>
<p class="formula">
@d_13=[10 - (sum_(i=1)^12 "alter"(i)*d_i) mod 10] mod 10@
</p>
<p>JavaScript implementation:</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
* Converts ISBN-13 string to digit array
*
* @param {string} isbn - ISBN-13 string representation
* @returns {number[]} array of digits, converted to numbers
*/</span>
<span class="kd">function</span> <span class="nx">toIsbnDigits</span><span class="p">(</span><span class="nx">isbn</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">[...</span><span class="nx">isbn</span><span class="p">].</span><span class="nx">map</span><span class="p">(</span><span class="nx">char</span> <span class="o">=></span> <span class="nb">Number</span><span class="p">.</span><span class="nb">parseInt</span><span class="p">(</span><span class="nx">char</span><span class="p">));</span>
<span class="p">}</span>
<span class="cm">/**
* Calculates check sum of ISBN-13
*
* @param {number[]} digits - ISBN-13 digit array
* @returns {number} check sum of ISBN-13
*/</span>
<span class="kd">function</span> <span class="nx">checksumIsbn13</span><span class="p">(</span><span class="nx">digits</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Helper function, returns 1 if x is odd, 3 otherwise</span>
<span class="kd">function</span> <span class="nx">factor</span><span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">(</span><span class="nx">x</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">===</span> <span class="mi">1</span><span class="p">)</span> <span class="p">?</span> <span class="mi">1</span> <span class="p">:</span> <span class="mi">3</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">let</span> <span class="nx">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="mi">12</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">sum</span> <span class="o">+=</span> <span class="nx">factor</span><span class="p">(</span><span class="nx">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="nx">digits</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
<span class="p">}</span>
<span class="k">return</span> <span class="p">(</span><span class="mi">10</span> <span class="o">-</span> <span class="p">(</span><span class="nx">sum</span> <span class="o">%</span> <span class="mi">10</span><span class="p">))</span> <span class="o">%</span> <span class="mi">10</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p><em>Thank you for reading!</em></p>
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
<script id="MathJax-script" async="" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<script>
MathJax = {
loader: {
load: ['input/asciimath']
},
asciimath: {
delimiters: [['@', '@']]
}
};
</script>Denis Tsvikevichdtsvikevich@gmail.comToday we will learn how to calculate SBN, ISBN-10 & ISBN-13 check digit and write these algorithms in JavaScript