title: Generating Luhn Checksums
body: <p>There are lots of implementations for validating Luhn checksums but very few for generating them. I've come across <a href="http://imei.sms.eu.sk/" rel="noreferrer">this one</a> however in my tests it has revealed to be buggy and I don't understand the logic behind the delta variable.</p>
  
  <p>I've made this function that supposedly should generated Luhn checksums but for some reason that I haven't yet understood the generated checksums are invalid half of the time.</p>
  
  <pre><code>function Luhn($number, $iterations = 1)
  {
      while ($iterations-- &gt;= 1)
      {
          $stack = 0;
          $parity = strlen($number) % 2;
          $number = str_split($number, 1);
  
          foreach ($number as $key =&gt; $value)
          {
              if ($key % 2 == $parity)
              {
                  $value *= 2;
  
                  if ($value &gt; 9)
                  {
                      $value -= 9;
                  }
              }
  
              $stack += $value;
          }
  
          $stack = 10 - $stack % 10;
  
          if ($stack == 10)
          {
              $stack = 0;
          }
  
          $number[] = $stack;
      }
  
      return implode('', $number);
  }
  </code></pre>
  
  <p>Some examples:</p>
  
  <pre><code>Luhn(3); // 37, invalid
  Luhn(37); // 372, valid
  Luhn(372); // 3728, invalid
  Luhn(3728); // 37283, valid
  Luhn(37283); // 372837, invalid
  Luhn(372837); // 3728375, valid
  </code></pre>
  
  <p>I'm validating the generated checksums <a href="http://planzero.org/bits/example_luhn_check" rel="noreferrer">against this page</a>, what am I doing wrong here?</p>
  
  <hr>
  
  <p><strong>For future reference, here is the working function.</strong></p>
  
  <pre><code>function Luhn($number, $iterations = 1)
  {
      while ($iterations-- &gt;= 1)
      {
          $stack = 0;
          $number = str_split(strrev($number), 1);
  
          foreach ($number as $key =&gt; $value)
          {
              if ($key % 2 == 0)
              {
                  $value = array_sum(str_split($value * 2, 1));
              }
  
              $stack += $value;
          }
  
          $stack %= 10;
  
          if ($stack != 0)
          {
              $stack -= 10;
          }
  
          $number = implode('', array_reverse($number)) . abs($stack);
      }
  
      return $number;
  }
  </code></pre>
  
  <p>I dropped the $parity variable since we don't need it for this purpose, and to verify:</p>
  
  <pre><code>function Luhn_Verify($number, $iterations = 1)
  {
      $result = substr($number, 0, - $iterations);
  
      if (Luhn($result, $iterations) == $number)
      {
          return $result;
      }
  
      return false;
  }
  </code></pre>