[RUBY] Roughly speed up the check digit check digit of My Number by about 10% (I don't know because I haven't measured it)

First, think carefully about the calculation method

Before .

First, let's take a closer look at how to calculate the inspection numbers (check digits). From the programmer's point of view, you can see that the calculation should be done by the following procedure.

  1. Put $ P and Q $ as follows. $ P $ is a list that includes the 11-digit number of My Number excluding the check digit as an element, and the element $ P_ {0} $ of $ P $ represents the first digit of the 11-digit number. And. Each element $ Q_n $ of $ Q $ is calculated as $ n \ bmod 6 + 2 $. However, $ n $ is $ 0 \ le n \ le 10 $.
    • P = (P_{10}, P_{9}, P_{8}, ..., P_{0})
    • Q = (Q_{10}, Q_{9}, Q_{8}, ..., Q_{0}) = (6, 5, 4, 3, 2, 7, 6, 5, 4, 3, 2)
  2. Find $ r = (11-\ sum_ {n = 1} ^ {11} P_n \ cdot Q_n \ bmod 11) \ bmod 10 $ and output $ r $ as an inspection number.

Once you know this, it's easy to write in any language. Since conditional branching does not appear, the execution speed is probably faster. Let's write it now.

Ruby

verify_my_number.rb


def verify_my_number(my_number)
  remain, given_check_digit = my_number.divmod(10)
  check_digit = 0

  11.times do |i|
    remain, p_i = remain.divmod(10)
    check_digit += p_i * (i % 6 + 2)
  end

  (11 - check_digit % 11) % 10 == given_check_digit
end

Perl

verify_my_number.pl


sub verify_my_number {
    my ($my_number) = @_;
    my $given_check_digit = $my_number % 10;
    my $check_digit = 0;

    for (my $i = 0; $i < 11; $i++) {
        $my_number /= 10;
        $check_digit += ($my_number % 10) * ($i % 6 + 2);
    }

    return (11 - $check_digit % 11) % 10 == $given_check_digit;
}

It's not so different from Ruby and it's not interesting, so I'll try another way of writing. I don't think there is an advantage in terms of speed just because it's a little fun to write.

verify_my_number2.pl


sub verify_my_number {
    my ($my_number) = @_;
    my $check_digit = 0;

    map {
        $check_digit += $my_number / (10 ** ($_ + 1)) % 10 * ($_ % 6 + 2);
    } (0 .. 10);

    return (11 - $check_digit % 11) % 10 == $my_number % 10;
}

C

verify_my_number.c


int
verify_my_number(long long int my_number)
{
        int check_digit = 0;
        int given_check_digit = my_number % 10;

        for (int i = 0; i < 11; i++) {
                my_number /= 10;
                check_digit += (my_number % 10) * (i % 6 + 2);
        }

        return (11 - check_digit % 11) % 10 == given_check_digit;
}

Go

verify_my_number.go


func verify_my_number(my_number int) bool {
    check_digit := 0
    given_check_digit := my_number % 10

    for i := 0; i < 11; i++ {
        my_number /= 10
        check_digit += (my_number % 10) * (i % 6 + 2)
    }

    return (11 - check_digit % 11) % 10 == given_check_digit
}

bash

verify_my_number.sh


function verify_my_number {
    n=`printf %012d $1`
    given_check_digit=$(($1 % 10))
    check_digit=`echo -n $n|grep -o .|paste -d\* - <(echo -n '654327654320'|grep -o .)|paste -d+ - - - - - - - - - - - -|sed -e 's/^/echo $(((11-(/' -e 's/$/)%11)%10))/'|sh`
    [ $check_digit -eq $given_check_digit ] && echo 'OK' || echo 'NG'
}

Excel If you just want to calculate the check digit, you can write as follows.

=MOD(
  11 - MOD(
  (MOD(QUOTIENT($A1, 10000000000), 10) * 6 +
   MOD(QUOTIENT($A1, 1000000000), 10) * 5 +
   MOD(QUOTIENT($A1, 100000000), 10) * 4 +
   MOD(QUOTIENT($A1, 10000000), 10) * 3 +
   MOD(QUOTIENT($A1, 1000000), 10) * 2 +
   MOD(QUOTIENT($A1, 100000), 10) * 7 +
   MOD(QUOTIENT($A1, 10000), 10) * 6 +
   MOD(QUOTIENT($A1, 1000), 10) * 5 +
   MOD(QUOTIENT($A1, 100), 10) * 4 +
   MOD(QUOTIENT($A1, 10), 10) * 3 +
   MOD($A1, 10) * 2),
  11),
10)

Python I'm not sure about Python, but maybe it looks like this? I don't think it's that fast.

verify_my_number.py


def verify_check_digit(my_number):
    product = sum([
                    (my_number / (10 ** (i + 1)) % 10) * (i % 6 + 2)
                    for i in range(0, 11)
                 ])
    return (11 - product % 11) % 10 == my_number % 10

Recommended Posts

Roughly speed up the check digit check digit of My Number by about 10% (I don't know because I haven't measured it)
[Summary of 27 languages] My number check digit calculation method
[You have to know it! ] I tried to set up a Python environment profitably by making full use of the privileges of university students.
I want to check the position of my face with OpenCV!