Python 如何计算巴拉圭国家税务ID的验证数字(calcular digito Verificator del RUC)

Python 如何计算巴拉圭国家税务ID的验证数字(calcular digito Verificator del RUC),python,Python,在巴拉圭(南美洲)国家,每个纳税人都有一个由政府指定的税号(称为RUC:RegistroÚnico del Contribuente)(农业部长) 该RUC是一个数字,后跟一个验证数字(dígito Verificator),例如123456-0。当您申请RUC时,政府会告诉您验证数字 我是否有办法根据RUC计算验证数字?这是一个已知的公式吗 就我而言,我有一个供应商和客户的数据库,多年来由公司的几名员工收集。 现在我需要进行检查,看看是否所有的RUC都输入正确,或者是否有打字错误 我的首选是P

在巴拉圭(南美洲)国家,每个纳税人都有一个由政府指定的税号(称为RUC:RegistroÚnico del Contribuente)(农业部长)

该RUC是一个数字,后跟一个验证数字(dígito Verificator),例如
123456-0
。当您申请RUC时,政府会告诉您验证数字

我是否有办法根据RUC计算验证数字?这是一个已知的公式吗

就我而言,我有一个供应商和客户的数据库,多年来由公司的几名员工收集。 现在我需要进行检查,看看是否所有的RUC都输入正确,或者是否有打字错误

我的首选是
Python
解决方案,但我会选择任何能为我指明正确方向的解决方案



编辑:这是一个分享知识的自我回答,我花了数小时/数天才找到。我将这个问题标记为“回答你自己的问题”(不知道这是否会改变任何东西)。

RUC的验证数字是使用非常类似(但不等于)的公式计算的,该公式称为
模11
;这至少是我在阅读以下科技网站时得到的信息(内容是西班牙语):

我分析了上述页面中提供的解决方案,并针对RUC列表及其已知验证数字运行了自己的测试,这使我得出了最终公式,该公式返回预期输出,但与上述链接中的解决方案不同


我得到的计算RUC验证数字的最终公式如本例所示(
80009735-1
):

  • 将RUC的每个数字(不考虑验证数字)乘以基于数字在RUC内的位置的系数(从RUC的右侧开始),并将这些乘法的所有结果相加:

    RUC:             8       0       0       0       9       7       3       5
    
    Position:        7       6       5       4       3       2       1       0
    
    Multiplications: 8x(7+2) 0x(6+2) 0x(5+2) 0x(4+2) 9x(3+2) 7x(2+2) 3x(1+2) 5x(0+2)
    
    Results:         72      0       0       0       45      28      9       10
    
    Sum of results:  164
    
  • 将总和除以
    11
    ,并使用除法的剩余部分确定验证数字:

    • 如果余数大于
      1
      ,则验证数字为
      11-余数
    • 如果余数为
      0
      1
      ,则验证数字为
      0
    输入输出示例:

    Sum of results:       164
    
    Division:             164 / 11    ==>   quotient 14, remainder 10
    
    Verification digit:   11 - 10     ==>   1
    

  • 这是我的
    Python
    版本的公式:

    def calculate_dv_of_ruc(input_str):
        # assure that we have a string
        if not isinstance(input_str, str):
            input_str = str(input_str)
    
        # try to convert to 'int' to validate that it contains only digits.
        # I suspect that this is faster than checking each char independently
        int(input_str)
    
        the_sum = 0
        for i, c in enumerate(reversed(input_str)):
            the_sum += (i + 2) * int(c)
    
        base = 11
        _, rem = divmod(the_sum, base)
        if rem > 1:
            dv = base - rem
        else:
            dv = 0
    
        return dv
    
    测试此函数时,它会返回预期结果,当输入包含除数字以外的其他字符时,会引发错误:

    >>> calculate_dv_of_ruc(80009735)
    1
    >>> calculate_dv_of_ruc('80009735')
    1
    >>> calculate_dv_of_ruc('80009735A')
    Traceback (most recent call last):
      File "<input>", line 1, in <module>
      File "<input>", line 8, in calculate_dv_of_ruc
    ValueError: invalid literal for int() with base 10: '80009735A'
    
    >>计算ruc(80009735)的
    1.
    >>>计算ruc的DVU('80009735')
    1.
    >>>计算ruc('80009735A')的
    回溯(最近一次呼叫最后一次):
    文件“”,第1行,在
    文件“”,第8行,在ruc的计算中
    ValueError:基数为10的int()的文本无效:“80009735A”
    
    RUC的验证数字是使用与称为模11的方法非常类似(但不等于)的公式计算的;这至少是我在阅读以下科技网站时得到的信息(内容是西班牙语):

    我分析了上述页面中提供的解决方案,并针对RUC列表及其已知验证数字运行了自己的测试,这使我得出了最终公式,该公式返回预期输出,但与上述链接中的解决方案不同


    我得到的计算RUC验证数字的最终公式如本例所示(
    80009735-1
    ):

  • 将RUC的每个数字(不考虑验证数字)乘以基于数字在RUC内的位置的系数(从RUC的右侧开始),并将这些乘法的所有结果相加:

    RUC:             8       0       0       0       9       7       3       5
    
    Position:        7       6       5       4       3       2       1       0
    
    Multiplications: 8x(7+2) 0x(6+2) 0x(5+2) 0x(4+2) 9x(3+2) 7x(2+2) 3x(1+2) 5x(0+2)
    
    Results:         72      0       0       0       45      28      9       10
    
    Sum of results:  164
    
  • 将总和除以
    11
    ,并使用除法的剩余部分确定验证数字:

    • 如果余数大于
      1
      ,则验证数字为
      11-余数
    • 如果余数为
      0
      1
      ,则验证数字为
      0
    输入输出示例:

    Sum of results:       164
    
    Division:             164 / 11    ==>   quotient 14, remainder 10
    
    Verification digit:   11 - 10     ==>   1
    

  • 这是我的
    Python
    版本的公式:

    def calculate_dv_of_ruc(input_str):
        # assure that we have a string
        if not isinstance(input_str, str):
            input_str = str(input_str)
    
        # try to convert to 'int' to validate that it contains only digits.
        # I suspect that this is faster than checking each char independently
        int(input_str)
    
        the_sum = 0
        for i, c in enumerate(reversed(input_str)):
            the_sum += (i + 2) * int(c)
    
        base = 11
        _, rem = divmod(the_sum, base)
        if rem > 1:
            dv = base - rem
        else:
            dv = 0
    
        return dv
    
    测试此函数时,它会返回预期结果,当输入包含除数字以外的其他字符时,会引发错误:

    >>> calculate_dv_of_ruc(80009735)
    1
    >>> calculate_dv_of_ruc('80009735')
    1
    >>> calculate_dv_of_ruc('80009735A')
    Traceback (most recent call last):
      File "<input>", line 1, in <module>
      File "<input>", line 8, in calculate_dv_of_ruc
    ValueError: invalid literal for int() with base 10: '80009735A'
    
    >>计算ruc(80009735)的
    1.
    >>>计算ruc的DVU('80009735')
    1.
    >>>计算ruc('80009735A')的
    回溯(最近一次呼叫最后一次):
    文件“”,第1行,在
    文件“”,第8行,在ruc的计算中
    ValueError:基数为10的int()的文本无效:“80009735A”
    
    如果不清楚:这是一个分享知识的自我回答,我花了数小时/数天才找到。我把这个问题标记为“回答你自己的问题”;虽然这是一个有趣的问题,也可能是有价值的信息,但我认为这与堆栈溢出无关。主要的问题似乎是收集和组装可用的资源,而不是实际的编程问题。你也可以写或更新一篇关于这个主题的维基百科文章。@mkrieger1我想我理解你的观点,但我有点不同意。维基百科可能也是一个不错的地方,但程序员最有可能询问计算RUC数字的方法,他们更有可能在StackOverflow中找到答案。当然,如果这是一个问题,我可以尝试以不同的方式表述/表达这个问题。如果不清楚:这是一个分享知识的自我回答,我花了数小时/数天的时间才找到。我把这个问题标记为“回答你自己的问题”;虽然这是一个有趣的问题,也可能是有价值的信息,但我认为这与堆栈溢出无关。主要的问题似乎是收集和组装