0

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.

user2025696
  • 159
  • 1
  • 11
  • 1
    I don't think that's the problem. Wiki says 1 <= x <= 8 which is position in the string. In perl, that translates fairly well to 0 < x < 8 because perl arrays are zero based. – Sobrique Jan 22 '15 at 20:35
  • ... I stand corrected. That's one of the problems. Non integer division seems to be the other one. – Sobrique Jan 22 '15 at 21:01
  • Made the suggested modifications to the odd/even check and the int() and now the function works. Thanks for the help all. – user2025696 Jan 22 '15 at 21:19
  • Any particular reason you aren't using CPAN modules? When I was dealing with the issue, I found at least 3 for CUSIP validation – DVK Jan 22 '15 at 21:32
  • @DVK because work wont allow me to install or download any new modules that aren't already on our desktops or servers. Or i would have definitely have used one of them. – user2025696 Jan 22 '15 at 21:36

1 Answers1

2

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;
}
Sobrique
  • 52,974
  • 7
  • 60
  • 101
  • That helped for the sample above but when i tried `cusip_check_digit('68243Q10')` it returned 5 when it should have returned 6. Getting closer though. – user2025696 Jan 22 '15 at 20:40
  • Hmm, possibly the same problem, but rounding error/integer divison. `use integer;` at the start might be a more elegant solution overall. (But doesn't change the result in the second example). – Sobrique Jan 22 '15 at 20:49
  • 1
    Ah, got it - you're testing even/odd incorrectly, because you 'step' the range - where the Wiki goes 1..8 this goes 0..7. – Sobrique Jan 22 '15 at 20:55
  • That did the trick, i'm testing with many more as we speak. But pretty sure that was the issue besides the `int ()`. – user2025696 Jan 22 '15 at 21:01