4

我正在编写一个 gem 来检测跟踪号(称为tracking_number,natch)。它在文本中搜索有效的跟踪号格式,然后通过每个服务规范中指定的校验和计算来运行这些格式以确定有效的号码。

前几天,我使用 USPS Certified Mail 邮寄了一封信,从 USPS 获得了随附的跟踪号,并将其输入我的 gem,但验证失败。我相当确定我正确地执行了计算,但是已经没有想法了。

该号码使用 USS 代码 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 才能有效。但是,谷歌的跟踪号自动检测可以按原样提取号码,所以我只能假设我做错了什么。

4

2 回答 2

10

根据我的手动计算,它应该与您的代码相匹配:

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 跟踪器页面时,我可以看到它的整个路径。


事实上,如果您查看出版物 91(确认服务技术指南),您会发现它使用了两个额外的数字,包括91前面用于跟踪应用程序 ID 的数字。应用在出版物中找到的算法为我们提供了:

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 以获取信息。

于 2011-02-22T04:22:52.097 回答
2

我不知道 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('-', ''))
于 2011-02-22T04:13:41.053 回答