Subject: | Sedol fails on non-numeric, check digit 0 written as 10 |
Sedol validation/check digit generation currently fails when the sedol
contains letter characters. Additionally, sedols with a check digit of
0 are written with '10' instead, because of a misplaced parenthesis near
the modulo operator; e.g. CheckDigits('sedol')->complete('232977')
produces 23297710 rather than 2329770. A patch and unit test file are
attached.
Subject: | sedol.t |
use Test::More tests => 67;
BEGIN { use_ok 'Algorithm::CheckDigits' };
my $sedol = CheckDigits( 'sedol' );
isa_ok( $sedol, 'Algorithm::CheckDigits' );
my %sedols = (
228276 => 5,
232977 => 0,
406566 => 3,
557910 => 7,
585284 => 2,
710889 => 9,
B00030 => 0,
B01841 => 1,
B0YBKJ => 7,
B0YBKL => 9,
B0YBKR => 5,
B0YBKT => 7,
B0YBLH => 2,
);
for my $base ( sort keys %sedols )
{
my $check = $sedols{$base};
my $full = $base . $check;
is $sedol->complete( $base ), $full, "$base -> $full";
ok $sedol->is_valid( $full ), "$full is valid";
is $sedol->basenumber( $full ), $base, "$full base is $base";
is $sedol->checkdigit( $full ), $check, "$full check is $check";
my $bad = $base . ($check eq '0' ? '1' : '0');
ok !$sedol->is_valid( $bad ), "$bad has wrong check digit";
}
Subject: | sedol.diff |
--- old/lib/Algorithm/CheckDigits/M10_008.pm 2010-11-12 13:40:53.000000000 -0500
+++ new/lib/Algorithm/CheckDigits/M10_008.pm 2011-03-02 19:19:54.971029000 -0500
@@ -11,6 +11,19 @@
my @weight = ( 1,3,1,7,3,9,1 );
+my %ctable = (
+ '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4,
+ '5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 9,
+ 'B' => 11, 'C' => 12, 'D' => 13,
+ 'F' => 15, 'G' => 16, 'H' => 17, 'J' => 19,
+ 'K' => 20, 'L' => 21, 'M' => 22, 'N' => 23,
+ 'P' => 25, 'Q' => 26, 'R' => 27, 'S' => 28, 'T' => 29,
+ 'V' => 31, 'W' => 32, 'X' => 33, 'Y' => 34,
+ 'Z' => 35,
+);
+
+my $sedol_chars = join '', sort keys %ctable;
+
sub new {
my $proto = shift;
my $type = shift;
@@ -22,7 +35,7 @@
sub is_valid {
my ($self,$number) = @_;
- if ($number =~ /^(\d{6})(\d)$/) {
+ if ($number =~ /^([$sedol_chars]{6})(\d)$/o) {
return $2 == $self->_compute_checkdigit($1);
}
return ''
@@ -30,7 +43,7 @@
sub complete {
my ($self,$number) = @_;
- if ($number =~ /^\d{6}$/) {
+ if ($number =~ /^[$sedol_chars]{6}$/o) {
return $number . $self->_compute_checkdigit($number);
}
return '';
@@ -38,7 +51,7 @@
sub basenumber {
my ($self,$number) = @_;
- if ($number =~ /^(\d{6})(\d)$/) {
+ if ($number =~ /^([$sedol_chars]{6})(\d)$/o) {
return $1 if ($2 == $self->_compute_checkdigit($1));
}
return '';
@@ -46,7 +59,7 @@
sub checkdigit {
my ($self,$number) = @_;
- if ($number =~ /^(\d{6})(\d)$/) {
+ if ($number =~ /^([$sedol_chars]{6})(\d)$/o) {
return $2 if ($2 == $self->_compute_checkdigit($1));
}
return '';
@@ -56,9 +69,9 @@
my $self = shift;
my $number = shift;
- if ($number =~ /^\d{6}$/) {
+ if ($number =~ /^[$sedol_chars]{6}$/o) {
- my @digits = split(//,$number);
+ my @digits = map { $ctable{$_} } split(//,$number);
my $sum = 0;
for (my $i = 0; $i <= $#digits; $i++) {
@@ -66,7 +79,7 @@
$sum += $weight[$i] * $digits[$i];
}
- return (10 - ($sum % 10) % 10);
+ return (10 - ($sum % 10)) % 10;
}
return -1;
} # _compute_checkdigit()