I have implemented the "MOD 10" check digit algorithm using SQL, for the US Postal Service Address Change Service Keyline according to the method in their document, but it seems I'm getting the wrong numbers! Our input strings have only numbers in them, making the calculation a little easier. When I compare my results with the results from their testing application, I get different numbers. I don't understand what is going on? Does anyone see anything wrong with my algorithm? It's got to be something obvious...
The documentation for the method can be found on page 12-13 of this document: http://www.usps.com/cpim/ftp/pubs/pub8a.pdf
The sample application can be found at: http://ribbs.usps.gov/acs/documents/tech_guides/KEYLINE.EXE
PLEASE NOTE: I fixed the code below, based on the help from forum users. This is so that future readers will be able to use the code in its entirety.
ALTER function [dbo].[udf_create_acs] (@MasterCustomerId varchar(26))
returns varchar(30)
as
begin
--this implements the "mod 10" check digit calculation
--for the US Postal Service ACS function, from "Publication 8A"
--found at "http://www.usps.com/cpim/ftp/pubs/pub8a.pdf"
declare @result varchar(30)
declare @current_char int
declare @char_positions_odd varchar(10)
declare @char_positions_even varchar(10)
declare @total_value int
declare @check_digit varchar(1)
--These strings represent the pre-calculated values of each character
--Example: '7' in an odd position in the input becomes 14, which is 1+4=5
-- so the '7' is in position 5 in the string - zero-indexed
set @char_positions_odd = '0516273849'
set @char_positions_even = '0123456789'
set @total_value = 0
set @current_char = 1
--stepping through the string one character at a time
while (@current_char <= len(@MasterCustomerId)) begin
--this is the calculation for the character's weighted value
if (@current_char % 2 = 0) begin
--it is an even position, so just add the digit's value
set @total_value = @total_value + convert(int, substring(@MasterCustomerId, @current_char, 1))
end else begin
--it is an odd position, so add the pre-calculated value for the digit
set @total_value = @total_value + (charindex(substring(@MasterCustomerId, @current_char, 1), @char_positions_odd) - 1)
end
set @current_char = @current_char + 1
end
--find the check digit (character) using the formula in the USPS document
set @check_digit = convert(varchar,(10 - (@total_value % 10)) % 10)
set @result = '#' + @MasterCustomerId + ' ' + @check_digit + '#'
return @result
end
set @check_digit = convert(varchar, (10 - (@total_value % 10)) % 10)