Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Zero Padding

by Anonymous Monk
on Feb 03, 2001 at 01:07 UTC ( [id://56103]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I've got a number such as 13 that I'd like to be 000013. Just need to add some zeros on the front. My first attempt was to find a printf line that did this. I couldn't find one :-( I'm currently using sprintf followed by s/ /0/g; Its terrible. What would be the preferred way to do this?

Thanks

Replies are listed 'Best First'.
Re: Zero Padding
by chipmunk (Parson) on Feb 03, 2001 at 01:10 UTC
    You can do this just using sprintf: $padded = sprintf "%06d", 13; The zero after the percent sign says to pad with zeros instead of spaces.
Re: Zero Padding
by autark (Friar) on Feb 03, 2001 at 01:10 UTC
    Well, printf works fine as long as you find the right template: printf("%06d", 13); Autark.
Re: Zero Padding
by runrig (Abbot) on Feb 03, 2001 at 01:12 UTC
    This is one area where the perldocs don't help much. But on most *nix systems you can 'man printf' or 'man sprintf' to get the relevant docs. Or find online Unix man pages.. or just give you the answer: 'printf("%06d", $variable)'

    Ok, so I'm wrong, you can now find the relevant info with 'perldoc -f sprintf' or even here: sprintf.

Re: Zero Padding
by footpad (Abbot) on Feb 03, 2001 at 09:07 UTC
Re: Zero Padding
by dystrophy (Monk) on Feb 03, 2001 at 06:27 UTC
    If you had done a search, you probably would have come up with Padding Out Strings, although this discussion went a tad deeper then that one.

    There are other uses for padding zeros than homework you know. Image frame numbers for instance - the padded zeros help OSs list the frames in the correct order. (speaking from experience, having written innumerable little scripts that do strange and wonderful things to a large number of frames)

    - dystrophy -
Re: Zero Padding
by mkmcconn (Chaplain) on Feb 03, 2001 at 22:40 UTC

    Variation on a theme, with a twist that I don't think has been mentioned. I've tried to do my homework, and nothing stood out that would break this. What do you think?

    #!/usr/bin/perl -wl use strict; my @numberarray = qw(1 120 13); lengthy(@numberarray); sub lengthy { s{ ( ^ ) } { ( "0" x (6-length $_) ) }xe and print for @_; } __END__

    Or, for the commandline:
    perl -wle ' s/^/("0"x(6-length))/xe and print for @ARGV;' 133 121 10 13
    Or, to make sure that it doesn't zero-pad alphabetical input
    perl -wle ' s{(^)(\d+$)}{("0"x(6-length).$2)}xe and print for @ARGV;' 1 fish 002 fish 333 blue fish
    And, to print all the arguments, but zero-padding only the numerical arguments:
    perl -wle ' s{(^)(\d+$)}{("0"x(6-length).$2)}xe and print or print for @ARGV;' 1 fish 002 fish 333 blue fish

    (Sir...put your hands up and please, step away from the keyboard)
    One more.. to pad words with spaces, instead of zeros.

    perl -wle ' s/^(\d+)/("0"x(6-length).$1)/xe and print or s/^(\w)/("\x20"x(6-length).$1)/xe and print for @ARGV;' 133 121 10 + 13 red

    mkmcconn
    (I'm gratified by how much better it is than this a few short weeks later. Thanks Perl Monks.).

Re: Zero Padding
by tune (Curate) on Feb 03, 2001 at 03:37 UTC
    And if you dont want to use printf()/sprintf() because it slows your script down just work it out by yourself:
    #!/usr/bin/perl $a=13; $length=6; while (length($a)<$length) {$a="0$a";} print $a;

    -- tune

      A quick Benchmark will show that this repeated concatenation is slower than sprintf:
      #!/usr/local/bin/perl use Benchmark; my $var=13; my $length=6; timethese(100000, { CONCAT=>\&concat, SPRINTF=>\&spr_f, }); sub concat { my $a = $var; while (length($a)<$length) {$a="0$a";} } sub spr_f { my $a = $var; sprintf("%0$length", $a); } Results: Benchmark: timing 100000 iterations of CONCAT, SPRINTF... CONCAT: 2 wallclock secs ( 1.53 usr + 0.00 sys = 1.53 CPU) @ 65 +359.48/s (n=100000) SPRINTF: 0 wallclock secs ( 0.60 usr + 0.00 sys = 0.60 CPU) @ 16 +6666.67/s (n=100000)
      UpdateOops, fixed the bug, tye's right that it doesn't change the result much, but I didn't really want to return the correct value in concat() or make spr_f() extra fast, just wanted to compare the process to create the desired result.

        You had a bug in spr_f() (you end up using a format of "%06" instead of "%06d"). That didn't seem to affect the speed much, though. You also don't return the correct value from concat() so I fixed that too. I made spr_f() a bit faster by eliminating the extra copy. This penalizes concat() since it is now the only one that needs the extra copy (oh well).

        I added my favorite (that I learned from chip) and reran the benchmark:

        #!/usr/bin/perl -w use strict; use Benchmark qw( cmpthese ); my $num= 13; my $wid= 6; sub concat { my $a= $num; $a= "0$a" while length($a) < $wid; $a; } sub spr_f { sprintf( "%0${wid}d", $num ); } sub sub_s { substr( "0"x$wid.$num, -$wid ); } cmpthese( -3, { CONCAT => \&concat, SPRINTF => \&spr_f, SUBSTR => \&sub_s, }); __END__ Your Results: Benchmark: timing 100000 iterations of CONCAT, SPRINTF... CONCAT: 65359.48/s SPRINTF: 166666.67/s Mine: Rate CONCAT SPRINTF SUBSTR CONCAT 98370/s -- -62% -66% SPRINTF 257009/s 161% -- -10% SUBSTR 286165/s 191% 11% --

        Looks like the substr() is fastest.

                - tye (but my friends call me "Tye")
        True, but it should be obvious without pulling out Benchmark that the algorithm is quadratic. Just look at how much recopying of data there is.

        *shrug*

        try this
        $foo = 0000
        $foo .= $number
      tune: while (length($a)<$length) {$a="0$a";}

      Humm.. why use a while loop. Wouldn't this be faster?

      $number = '0' x (5 - length($number)) . $number;

      // Martin
Re: Zero Padding
by ftforger (Sexton) on Feb 03, 2001 at 03:54 UTC
    Sounds an awful lot like a high school homework project to me. (Or part of one at least)
      Maybe, but the seeker didn't just copy and past the assignment, like some others. He asked for the best way to perform a very specific task, and demonstrated that he had read the docs enough to know that (s)printf was the right function to use, and even had a working, though suboptimal solution. A "this is homework" disclaimer is always nice, but I think this post is ok without it (even assuming it is homework).

      --
      Ryan Koppenhaver, Aspiring Perl Hacker
      "I ask for so little. Just fear me, love me, do as I say and I will be your slave."

Re: Zero Padding
by Yoda (Sexton) on Feb 04, 2001 at 17:43 UTC
    Ok, Something short and quick
    $num = 13; $len = 6; $padnum = 0 x ($len - length($num)) . $num;
    Yoda

      I posted a similar solution here, but with one difference - the 0 was quoted.

      At first glance, you might think "So what?", but in benchmarks it actually was 25% faster than the unquoted version.

      I assume this is because perl has to do less work to figure out the context of 0 and transform it into a string.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://56103]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (3)
As of 2024-04-24 02:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found