algorithmperlfinancialcheck-digit

Is there a way to check digits of a CUSIP in Perl


My work place won't allow us to install any modules so that option isn't for me. So decided to look at this link http://en.wikipedia.org/wiki/CUSIP and follow the pseudocode there and attempt to code it in Perl.

And i came up with the following:

sub cusip_check_digit
{
    my $cusip = shift;                    ## Input: an 8-character CUSIP
    my $v = 0;                            ## numeric value of the digit c (below)

    my $sum = 0;
    for (my $i = 0; $i < 8; $i++)
    {
        my $c = substr ($cusip, $i, 1);   ## $c is the ith character of cusip          
        if ($c =~ /\d/)                   ## c is a digit then
        {
            $v = $c;                      ## numeric value of the digit c
        }
        elsif ($c =~ /\w/)
        {
            my $p = ord($c) - 64;         ##  ordinal position of c in the alphabet (A=1, B=2...)
            $v = $p + 9;
        }

        if (0 != $i % 2)                  ## check to see if $i is even (we invert due to Perl starting points)
        {
            $v = $v * 2;
        }

        $sum = $sum + int ($v / 10) + $v % 10;

    }

    $v = (10 - ($sum % 10)) % 10;
    print "v is: $v\n";

    #return (10 - ($sum % 10)) % 10
}

cusip_check_digit('90137F10');   ## should return 3 ** Now works **
cusip_check_digit('68243Q10');   ## should return 6 ** Now works **

Not exactly sure why it isn't working.


Solution

  • I think your problem is this line:

    $sum = $sum + $v / 10 + $v % 10;
    

    The wiki says 'div' and 'mod'. Which implies integer division, and that's not what it's doing.

    Change it to:

    $sum = $sum + int ( $v / 10 ) + $v % 10;
    

    And you get the desired result of '3'. I haven't checked it with any other values though, so you'd probably best check.

    Edit: Second problem is because we run from 0 to 7 rather than 1 to 8 like in the example. That means 'is i even' test gets the wrong digit. Easy enough to solve by inverting the logic (test for 'odd' not 'even').

    Change that bit to:

    if (0 != $i % 2) {
        $v = $v * 2;
    }