Dirk Bremer wrote:

> Here is a quicker version of the zero-suppression routine that will also float a 
>leading sign character:
> 
>     sub ZeroSuppress2($)
>     {
>         my $self = shift;
> 
>         # Return if the argument is less than two digits.
>         return($self) if (length($self) < 2);
> 
>         # Search for a embedded decimal point.
>         my $decimal  = rindex($self,'.');
> 
>         # If the decimal point exists, substract one from its position
>         # to define the end point of the zero-suppression, else determine
>         # the entire length of the string and subtract one to define the
>         # end point of the zero-suppression.
>         if ($decimal > 0) {$decimal-- ;}
>         else {$decimal = length($self) - 1;}
> 
>         # Iterate through the list suppressing leading zeroes.
>         my $i;
>         my $c;
>         for ($i = 0; $i < $decimal; $i++)
>         {
>             $c = substr($self,$i,1);
>             # Skip to the next character if the current character is a
>             # plus-sign, minus-sign, or space.
>             next if ($c eq ' ' or
>                      $c eq '+' or
>                      $c eq '-');
> 
>             # Terminate the loop if the current character is s digit.
>             last if ($c > 0);
> 
>             # Replace the zero in the current character with a space.
>             substr($self,$i,1) = ' ';
>         }
> 
>         $c = substr($self,0,1);
>         # Check for a leading sign-character.
>         if ($c eq '+' or $c eq '-')
>         {
>             # If the list has more two elements, move the sign-character
>             # from the leftmost position to the position of the rightmost
>             # space character.
>             if ($i > 1) {substr($self,$i - 1,1) = $c; substr($self,0,1) = ' ';}
>         }
> 
>         return($self);
>     }
> 
> After running some more benchmarks, this routine is several orders of magnitude 
>faster than sprinf or a regex. 


I modified your routine a bit to handle replacing 0's with blanks or
just removing  the leading 0's.  My benchmark show the RE to be faster
unless I made a mistake somewhere.

sub ZeroSuppress2 ($;$) {
        my $self = shift;
        my $replace = shift || 0;

# Return if the argument is less than two digits.

return $self if length ($self) < 2;

# Search for a embedded decimal point.
# If the decimal point exists, substract one from its position
# to define the end point of the zero-suppression, else determine
# the entire length of the string and subtract one to define the
# end point of the zero-suppression.

my $decimal  = rindex ($self, '.') - 1;
$decimal = length ($self) - 1 if $decimal < 0;

# Iterate through the list suppressing leading zeroes.

my ($c, $i);
for ($i = 0; $i < $decimal; $i++) {

        $c = substr ($self, $i, 1);

        # Skip to the next character if the current character is a
        # plus-sign, minus-sign, or space.

        next if $c eq ' ' or $c eq '+' or $c eq '-';

        # Terminate the loop if the current character is s digit.

        last if ($c gt '0');

        # Replace the zero in the current character with a space.

        if ($replace) {
                substr ($self, $i, 1) = ' ';
        } else {
                $self = substr ($self, 0, $i) . substr ($self, $i+1);
                $i--; $decimal--;
        }
}

$c = substr ($self, 0, 1);

# Check for a leading sign-character.

if ($replace and $c eq '+' or $c eq '-') {

        # If the list has more two elements, move the sign-character
        # from the leftmost position to the position of the rightmost
        # space character.

        if ($i > 1) {
                substr ($self, $i - 1, 1) = $c;
                substr ($self, 0, 1) = ' ';
        }
}

return $self;

}

sub ZeroSuppress3 ($;$) {
        local $_ = shift;
        my $replace = shift || 0;

if ($replace) {
        1 while s/(?<!\.)\b0(?=\d)/ /;
        s/([-+])(\s+)/$2$1/;
} else {
        s/(?<!\.)\b0+(?=\d)//;
}
return $_;

}

use Benchmark;
my $num = '000001.001';
timethese (400_000, {

'ZS2' => "ZeroSuppress2 ($num, 0)",
'ZS3' => "ZeroSuppress3 ($num, 0)",

'ZS2r' => "ZeroSuppress2 ($num, 1)", # replace 0's with blanks
'ZS3r' => "ZeroSuppress3 ($num, 1)",

});

my $num = '000001.001';
Benchmark: timing 400000 iterations of ZS2, ZS2r, ZS3, ZS3r...
        ZS2:  7 wallclock secs ( 6.59 usr +  0.00 sys =  6.59 CPU) @ 60698.03/s 
(n=400000)
       ZS2r:  6 wallclock secs ( 6.81 usr +  0.00 sys =  6.81 CPU) @ 58737.15/s 
(n=400000)
        ZS3:  4 wallclock secs ( 3.84 usr +  0.00 sys =  3.84 CPU) @ 104166.67/s 
(n=400000)
       ZS3r:  5 wallclock secs ( 5.66 usr +  0.00 sys =  5.66 CPU) @ 70671.38/s 
(n=400000)

my $num = '+000001.001';
Benchmark: timing 400000 iterations of ZS2, ZS2r, ZS3, ZS3r...
        ZS2:  9 wallclock secs ( 8.62 usr +  0.00 sys =  8.62 CPU) @ 46403.71/s 
(n=400000)
       ZS2r: 13 wallclock secs (12.14 usr +  0.00 sys = 12.14 CPU) @ 32948.93/s 
(n=400000)
        ZS3:  2 wallclock secs ( 2.64 usr +  0.00 sys =  2.64 CPU) @ 151515.15/s 
(n=400000)
       ZS3r:  3 wallclock secs ( 3.35 usr +  0.00 sys =  3.35 CPU) @ 119402.99/s 
(n=400000)

-- 
   ,-/-  __      _  _         $Bill Luebkert   ICQ=14439852
  (_/   /  )    // //       DBE Collectibles   Mailto:[EMAIL PROTECTED]
   / ) /--<  o // //      http://dbecoll.tripod.com/ (Free site for Perl)
-/-' /___/_<_</_</_     Castle of Medieval Myth & Magic http://www.todbe.com/

_______________________________________________
Perl-Win32-Users mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Reply via email to