From 84f8f1aed5c8e9f51bb9d93e9040c787cb1c311c Mon Sep 17 00:00:00 2001 From: Peter John Acklam Date: Thu, 4 Nov 2010 18:08:56 +0100 Subject: [PATCH] RT ticket #61812: digit($n) with $n "out of range" The _digit($n) method in Math::BigInt::Calc should return 0 when $n refers to a leading zero digit. E.g., the number '314' is just the same as '000314', except that the leading zeros omitted, so _digit($n) should return '0' when $n refers to a leading zero digit. - lib/Math/BigInt/Calc.pm: Improve comments in source code. Add code returning zero when input refers to a leading zero digit. Removed redundant zero padding in temporary string argument to substr(). - t/bigintc.t: Add four test cases verifying the behaviour. Increment number of test by four. --- dist/Math-BigInt/lib/Math/BigInt/Calc.pm | 18 ++++++++---------- dist/Math-BigInt/t/bigintc.t | 6 +++++- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/dist/Math-BigInt/lib/Math/BigInt/Calc.pm b/dist/Math-BigInt/lib/Math/BigInt/Calc.pm index f5f4ff1..af638f2 100644 --- a/dist/Math-BigInt/lib/Math/BigInt/Calc.pm +++ b/dist/Math-BigInt/lib/Math/BigInt/Calc.pm @@ -1206,20 +1206,18 @@ sub _len sub _digit { - # return the nth digit, negative values count backward - # zero is rightmost, so _digit(123,0) will give 3 + # Return the nth digit. Zero is rightmost, so _digit(123,0) gives 3. + # Negative values count from the left, so _digit(123, -1) gives 1. my ($c,$x,$n) = @_; my $len = _len('',$x); - $n = $len+$n if $n < 0; # -1 last, -2 second-to-last - $n = abs($n); # if negative was too big - $len--; $n = $len if $n > $len; # n to big? - - my $elem = int($n / $BASE_LEN); # which array element - my $digit = $n % $BASE_LEN; # which digit in this element - $elem = '0' x $BASE_LEN . @$x[$elem]; # get element padded with 0's - substr($elem,-$digit-1,1); + $n += $len if $n < 0; # -1 last, -2 second-to-last + return "0" if $n < 0 || $n >= $len; # return 0 for digits out of range + + my $elem = int($n / $BASE_LEN); # which array element + my $digit = $n % $BASE_LEN; # which digit in this element + substr("$x->[$elem]", -$digit-1, 1); } sub _zeros diff --git a/dist/Math-BigInt/t/bigintc.t b/dist/Math-BigInt/t/bigintc.t index 9b94aeb..3123ff8 100644 --- a/dist/Math-BigInt/t/bigintc.t +++ b/dist/Math-BigInt/t/bigintc.t @@ -1,7 +1,7 @@ #!/usr/bin/perl -w use strict; -use Test::More tests => 375; +use Test::More tests => 379; use Math::BigInt::Calc; @@ -129,9 +129,13 @@ $x = $C->_new("123456789"); is ($C->_digit($x,0),9); is ($C->_digit($x,1),8); is ($C->_digit($x,2),7); +is ($C->_digit($x,8),1); +is ($C->_digit($x,9),0); is ($C->_digit($x,-1),1); is ($C->_digit($x,-2),2); is ($C->_digit($x,-3),3); +is ($C->_digit($x,-9),9); +is ($C->_digit($x,-10),0); # _copy foreach (qw/ 1 12 123 1234 12345 123456 1234567 12345678 123456789/) -- 2.7.4