Late Night Check Digit Routines - National Provider Identifier
Check digit routines are fun. There is one for the “National Provider Identifier” that a friend alerted me to this evening. He undertook implementing the algorithm in Perl, and I agreed to do a version of it in Ruby (my new favorite language). Below, I’ve include the source, replete with comments that I implemented the algorithm by. This code is provided with NO WARRANTY. Let me know if you use this code, or if you find problems with it.
Download Link: National Provider Identifier Ruby Code
If you’re looking for more information on this topic, a couple of links are:
http://www.claredi.com/download/npi_resources.php
http://www.medavanthealth.com/implementation/npi/NPI_check_digit.pdf
#!/usr/bin/env ruby
# NPI Validation Routine
# The NPI validation is done as follows:
# 1 ) For the purposes of this validation routine, isolate the last
# digit of the NPI and do not use it in any steps outlined below;
# 2 ) Precede the NPI with 80840;
# 3 ) Double the value of alternate digits, beginning with the
# rightmost digit, remember that the check digit is not to be used;
# 4 ) Total the value of the individual digits from step #3;
# 5 ) Total the value of the unaffected digits;
# 6 ) Add the two sums from steps #4 and #5;
# 7 ) Take the sum of step #6 and go to the next higher number
# ending in zero;
# 8 ) Subtract the sum of step #6 from the next higher number
# ending in zero from step #7;
# 9 ) If the value in step #8 matches the last digit in the
# submitted NPI, the NPI is valid.
#
# Example of Check Digit Validation of the NPI
# The NPI submitted is 1234567893. The NPI validation is done as follows:
# 1 ) For the purposes of this validation routine, isolate the last
# digit of the NPI (3) and do not use it in any steps outlined below;
# 2 ) Precede the NPI with 80840 (8 0 8 4 0 1 2 3 4 5 6 7 8 9 3);
# 3 ) Double the value of alternate digits, beginning with the
# rightmost digit, remember that the check digit is not to be used (0 8 2
# 6 10 14 18);
# 4 ) Total the value of the individual digits from step #3
# (0+8+2+6+1+0+1+4+1+8) which equals 31;
# 5 ) Total the value of the unaffected digits (8+6+4+2+0+8+8)
# which equals 36;
# 6 ) Add the two sums from steps #4 and #5 (31+36) which equals 67;
# 7 ) Take the sum of step #6 and go to the next higher number
# ending in zero which is 70;
# 8 ) Subtract the sum of step #6 from the next higher number
# ending in zero from step #7 (70-67) and the value is 3;
# 9 ) The value in step #8 matches the last digit in the submitted
# NPI, therefore the NPI is valid.
# try running with: ./npi.rb 1234567893 1234567891 9876543213
# prime the ARGV pump, if nothing was passed in
ARGV[0] ||= "1234567893"
ARGV.each { |npi_orig|
#convert to array, leave off last digit, reverse it, convert to integer
npi = ("80840" + npi_orig[0..-2]).scan(/./).reverse.collect {|digit| digit.to_i}
total = 0;
npi.each_index {|index|
npi[index] = npi[index] * 2 unless ((index % 2) > 0);
# tally up the digits into total, even if there are multiple
npi[index].to_s.scan(/./).each{|digit| total += digit.to_i}
}
status = (npi_orig[-1..-1] == ((((total + 10) / 10).to_i * 10) - total).to_s)
? "" :" *NOT* "
puts "The number #{npi_orig} is#{status}a valid NPI"
}