title: Calculating modulus for large numbers in PL/SQL
body: <p>I'm trying to calculate big modulus in PL/SQL. I implemented a method that I found on this location: <a href="http://en.wikipedia.org/wiki/International_Bank_Account_Number" rel="noreferrer">http://en.wikipedia.org/wiki/International_Bank_Account_Number</a> under Modulo operation on IBAN. But I get wrong results when I use this number: 221021290110000123452229211210282900128222984.</p>
  
  <p>This is how the method needs to be done:</p>
  
  <p><em>Piece-wise calculation D mod 97 can be done in many ways. One such way is as follows:</em></p>
  
  <ol>
  <li>Starting from the leftmost digit of D, construct a number using the first 9 digits and call it N.</li>
  <li>Calculate N mod 97. If the result is less than 10, prefix the result with a 0, giving a result in the range 00 to 96.</li>
  <li>Construct a new 9-digit N by concatenating above result (step 2) with the next 7 digits of D. If there are fewer than 7 digits remaining in D but at least one, then construct a new N, which will have less than 9 digits, from the above result (step 2) followed by the remaining digits of D</li>
  <li>Repeat steps 2–3 until all the digits of D have been processed</li>
  </ol>
  
  <p>The result of the final calculation in step 2 will be D mod 97 = N mod 97.</p>
  
  <p>I did some logging, these are the results of all the modulo steps:</p>
  
  <pre><code>221021290110000123452229211210282900128222984 (221021290 % 97 = 0)
  00110000123452229211210282900128000000 (001100001 % 97 = 21)
  2123452229211210282900128000000 (212345222 &amp; 97 = 0)
  009211210282900128000000 (009211210 % 97 = 90)
  90282900128000000 (902829001 % 97 = 46)
  4628000000 (462800000 % 97 = 2)
  020 = 20
  </code></pre>
  
  <p>The result needs to be 1. I checked it with a modulo calculator and it needs to be 1. With most numbers the calcutor is correct.</p>
  
  <p>This is the code I made, how is it possible that this number isn't correct:</p>
  
  <pre><code>create or replace function doubleDiget (iban number)
  return varchar2
  as
  begin
    if(iban &lt;= 9) then
      return concat('0',iban);
    else
      return iban;
    end if;
  end doubleDiget;
  
  create or replace FUNCTION modbig (iban number)   
      RETURN varchar2                     
        AS  
        lengthIban number(38);
        modUitkomts number(38);
        modUitkomtsc varchar(38);
        restIban varchar(38);
        modlength number(38);
    BEGIN
  
    modUitkomts := SUBSTR(iban,0,9) mod 97;
    modUitkomtsc := doubleDiget(modUitkomts);
    restIban := concat(modUitkomtsc,SUBSTR(iban,10)); 
    dbms_output.put_line(restIban);
  
    loop
      if( length(restIban) &gt;= 9) then
          modUitkomts := SUBSTR(restIban,0,9) mod 97;
          modUitkomtsc := doubleDiget(modUitkomts);
          restIban := concat(modUitkomtsc,SUBSTR(restIban,10)); 
          dbms_output.put_line(restIban);
      else
        exit;
      end if;
    end loop;
  
    modUitkomts := restIban mod 97;
    return modUitkomts;
  
  
  END modbig;
  
  begin
  DBMS_OUTPUT.PUT_LINE(modbig(221021290110000123452229211210282900128222984));  
  end;
  </code></pre>