我正在写一个宝石来检测跟踪号码(称为tracking_number,natch)。它在文本中搜索有效的跟踪号格式,然后通过每个相应服务规范中指定的校验和计算来运行这些格式,以确定有效的数字。
前几天,我使用USPS认证邮件邮寄了一封信,从USPS获得了随附的跟踪号码,并将其输入我的宝石中,但未通过验证。我相当肯定我正在正确地执行计算,但是已经没有想法了。
使用USS Code 128验证号码,如以下文件的第2.8节(第15页)所述:http://www.usps.com/cpim/ftp/pubs/pub109.pdf
我从邮局得到的跟踪号是“7196 9010 7560 0307 7385”,我用来计算校验位的代码是:
def valid_checksum?
# tracking number doesn't have spaces at this point
chars = self.tracking_number.chars.to_a
check_digit = chars.pop
total = 0
chars.reverse.each_with_index do |c, i|
x = c.to_i
x *= 3 if i.even?
total += x
end
check = total % 10
check = 10 - check unless (check.zero?)
return true if check == check_digit.to_i
end
根据我提供的规格计算,最后一位数字应为3才能生效。但是,Google的跟踪号码自动检测功能可以很好地获取数字,因此我只能假设我做错了。
答案 0 :(得分:7)
从我的手动计算中,它应该与您的代码相符:
posn: 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 sum mult
even: 7 9 9 1 7 6 0 0 7 8 54 162
odd: 1 6 0 0 5 0 3 7 3 25 25
===
187
因此校验位应为三位。
如果该号码有效,那么他们使用的是不同的算法,而不是您认为的算法。
我认为可能就是这种情况,因为当我将您提供的号码插入USPS跟踪器页面时,我可以看到它的整个路径。
事实上,如果您查看确认服务技术指南publication 91,您会看到它使用两个额外的数字,包括跟踪应用程序ID前面的91
。应用 出版物中的算法给出了我们:
posn: 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 sum mult
even: 9 7 9 9 1 7 6 0 0 7 8 63 189
odd: 1 1 6 0 0 5 0 3 7 3 26 26
===
215
那确实给你一个5的校验位。我不是说这是答案,但它确实与事实相符,至少是一个可行的解释。
可能你最好的选择是联系USPS获取信息。
答案 1 :(得分:1)
我不知道Ruby,但看起来好像你在每个偶数上乘以3;以及我阅读规范的方式,你将所有偶数位相加并将总和乘以3.参见第20-21页的已完成的例子。
(稍后) 你的代码可能是对的。这个Python代码段为他们的示例提供了7个,为你的代码提供了3个:
#!/usr/bin/python
'check tracking number checksum'
import sys
def check(number = sys.argv[1:]):
to_check = ''.join(number).replace('-', '')
print to_check
even = sum(map(int, to_check[-2::-2]))
odd = sum(map(int, to_check[-3::-2]))
print even * 3 + odd
if __name__ == '__main__':
check(sys.argv[1:])
[稍后补充] 刚刚完成我的代码,供参考:
jcomeau@intrepid:~$ /tmp/track.py 7196 9010 7560 0307 7385
False
jcomeau@intrepid:~$ /tmp/track.py 91 7196 9010 7560 0307 7385
True
jcomeau@intrepid:~$ /tmp/track.py 71123456789123456787
True
jcomeau@intrepid:~$ cat /tmp/track.py
#!/usr/bin/python
'check tracking number checksum'
import sys
def check(number):
to_check = ''.join(number).replace('-', '')
even = sum(map(int, to_check[-2::-2]))
odd = sum(map(int, to_check[-3::-2]))
checksum = even * 3 + odd
checkdigit = (10 - (checksum % 10)) % 10
return checkdigit == int(to_check[-1])
if __name__ == '__main__':
print check(''.join(sys.argv[1:]).replace('-', ''))