printf: zero pad after the decimal a given amount

Discussion in 'Perl Misc' started by jidanni@jidanni.org, Mar 30, 2008.

  1. Guest

    Why is there no way to tell printf to zero pad like the right column:
    0.1 :0.100
    0.05 :0.050
    0.03 :0.030
    0.025 :0.025
    0.02 :0.020
    0.015 :0.015
    0.0125 :0.0125
    0.01 :0.010
    0.009 :0.009
    0.00625:0.00625
    0.005 :0.005
    The challenge: Change only the "WHAT?" below to produce the right
    column above. Thanks.
    use constant S => 100000;
    for ( 10000, 5000, 3000, 2500, 2000, 1500, 1250, 1000, 900, 625, 500 ) {
    printf "%-7g:WHAT?\n", $_ / S, $_ / S;
    }
     
    , Mar 30, 2008
    #1
    1. Advertising

  2. wrote:
    > Why is there no way to tell printf to zero pad like the right column:
    > 0.1 :0.100
    > 0.05 :0.050
    > 0.03 :0.030
    > 0.025 :0.025
    > 0.02 :0.020
    > 0.015 :0.015
    > 0.0125 :0.0125
    > 0.01 :0.010
    > 0.009 :0.009
    > 0.00625:0.00625
    > 0.005 :0.005
    > The challenge: Change only the "WHAT?" below to produce the right
    > column above. Thanks.
    > use constant S => 100000;
    > for ( 10000, 5000, 3000, 2500, 2000, 1500, 1250, 1000, 900, 625, 500 ) {
    > printf "%-7g:WHAT?\n", $_ / S, $_ / S;
    > }


    $ perl -le'
    use constant S => 100000;
    my $x;
    format =
    @<<<<<< : @.#####
    $x, $x
    ..
    for ( 10000, 5000, 3000, 2500, 2000, 1500, 1250, 1000, 900, 625, 500 ) {
    $x = $_ / S;
    write;
    }
    '
    0.1 : 0.10000
    0.05 : 0.05000
    0.03 : 0.03000
    0.025 : 0.02500
    0.02 : 0.02000
    0.015 : 0.01500
    0.0125 : 0.01250
    0.01 : 0.01000
    0.009 : 0.00900
    0.00625 : 0.00625
    0.005 : 0.00500



    John
    --
    Perl isn't a toolbox, but a small machine shop where you
    can special-order certain sorts of tools at low cost and
    in short order. -- Larry Wall
     
    John W. Krahn, Mar 31, 2008
    #2
    1. Advertising

  3. szr Guest

    wrote:
    > Why is there no way to tell printf to zero pad like the right column:
    > 0.1 :0.100
    > 0.05 :0.050
    > 0.03 :0.030
    > 0.025 :0.025
    > 0.02 :0.020
    > 0.015 :0.015
    > 0.0125 :0.0125
    > 0.01 :0.010
    > 0.009 :0.009
    > 0.00625:0.00625
    > 0.005 :0.005
    > The challenge: Change only the "WHAT?" below to produce the right
    > column above. Thanks.
    > use constant S => 100000;
    > for ( 10000, 5000, 3000, 2500, 2000, 1500, 1250, 1000, 900, 625, 500
    > ) { printf "%-7g:WHAT?\n", $_ / S, $_ / S;
    > }


    use constant S => 100000;
    for ( 10000, 5000, 3000, 2500, 2000, 1500, 1250, 1000, 900, 625, 500 ) {
    printf "%-7g:%01d.%3.3s%s\n", $_ / S, int $_ / S,
    sprintf("%05d", $_),
    map { $_ ? $_ : '' } ($_ % 100) =~ m!^(\d+?)0*$!;
    }

    __OUTPUT__
    0.1 :0.100
    0.05 :0.050
    0.03 :0.030
    0.025 :0.025
    0.02 :0.020
    0.015 :0.015
    0.0125 :0.0125
    0.01 :0.010
    0.009 :0.009
    0.00625:0.00625
    0.005 :0.005

    :)

    --
    szr
     
    szr, Mar 31, 2008
    #3
  4. Paul Lalli Guest

    On Mar 30, 4:09 pm, wrote:
    > Why is there no way to tell printf to zero pad like the right column:


    Why do you assume that because you don't know the way, there is no
    way?

    > 0.1    :0.100
    > 0.05   :0.050
    > 0.03   :0.030
    > 0.025  :0.025
    > 0.02   :0.020
    > 0.015  :0.015
    > 0.0125 :0.0125
    > 0.01   :0.010
    > 0.009  :0.009
    > 0.00625:0.00625
    > 0.005  :0.005
    > The challenge: Change only the "WHAT?" below to produce the right
    > column above. Thanks.
    > use constant S => 100000;
    > for ( 10000, 5000, 3000, 2500, 2000, 1500, 1250, 1000, 900, 625, 500 ) {
    >     printf "%-7g:WHAT?\n", $_ / S, $_ / S;
    >


    %.03f

    $ perl -e'printf("%.03f\n", .1)'
    0.100

    Paul Lalli
     
    Paul Lalli, Mar 31, 2008
    #4
  5. szr Guest

    Paul Lalli wrote:
    > On Mar 30, 4:09 pm, wrote:
    >> Why is there no way to tell printf to zero pad like the right column:

    >
    > Why do you assume that because you don't know the way, there is no
    > way?
    >
    >> 0.1 :0.100
    >> 0.05 :0.050
    >> 0.03 :0.030
    >> 0.025 :0.025
    >> 0.02 :0.020
    >> 0.015 :0.015
    >> 0.0125 :0.0125
    >> 0.01 :0.010
    >> 0.009 :0.009
    >> 0.00625:0.00625
    >> 0.005 :0.005
    >> The challenge: Change only the "WHAT?" below to produce the right
    >> column above. Thanks.
    >> use constant S => 100000;
    >> for ( 10000, 5000, 3000, 2500, 2000, 1500, 1250, 1000, 900, 625, 500
    >> ) { printf "%-7g:WHAT?\n", $_ / S, $_ / S;
    >>

    >
    > %.03f
    >
    > $ perl -e'printf("%.03f\n", .1)'
    > 0.100
    >
    > Paul Lalli


    Actually that truncates to 3 decimal places, which isn't what the op
    required:

    $ perl -e'printf("%.03f\n", .00625)'
    0.006


    See my other post for a working solution.

    --
    szr
     
    szr, Mar 31, 2008
    #5
  6. Dr.Ruud Guest

    schreef:
    > Why is there no way to tell printf to zero pad like the right column:
    > 0.1 :0.100
    > 0.05 :0.050
    > 0.03 :0.030
    > 0.025 :0.025
    > 0.02 :0.020
    > 0.015 :0.015
    > 0.0125 :0.0125
    > 0.01 :0.010
    > 0.009 :0.009
    > 0.00625:0.00625
    > 0.005 :0.005


    $ perl -wle'
    print "".reverse sprintf "%05.1f", "".reverse sprintf "%f", $_
    for qw/.1 .05 .03 .025 .02 .015 .0125 .01 .009 .00625 .005
    1.987654321E1/
    '
    0.100
    0.050
    0.030
    0.025
    0.020
    0.015
    0.0125
    0.010
    0.009
    0.00625
    0.005
    9.876543

    ;)

    --
    Affijn, Ruud

    "Gewoon is een tijger."
     
    Dr.Ruud, Mar 31, 2008
    #6
  7. Guest

    wrote:
    > Why is there no way to tell printf to zero pad like the right column:


    One reason is that what you want is ill-defined. If we are going to tweak
    sprintf to make it suit our personal preferences, I'd rather see a
    conversion character that behaved just like %f if given a good number, but
    returned the empty string if given either an empty string or undef (rather
    than converting it to zero and then applying %f to the zero.)

    > 0.1 :0.100
    > 0.05 :0.050
    > 0.03 :0.030
    > 0.025 :0.025
    > 0.02 :0.020
    > 0.015 :0.015


    Apparently you want to preserve non-zero digits even if that means going
    beyond 3 digits right of the decimal. But why did you stop at 4?

    0.014999999999999999444888

    > 0.0125 :0.0125



    0.0125000000000000006938893

    How many consecutive zeros or nines are needed before you decide there are
    enough to ignore what is the right of them?

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    The costs of publication of this article were defrayed in part by the
    payment of page charges. This article must therefore be hereby marked
    advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
    this fact.
     
    , Mar 31, 2008
    #7
  8. Ben Morrow Guest

    Quoth :
    > wrote:
    > > Why is there no way to tell printf to zero pad like the right column:

    >
    > One reason is that what you want is ill-defined. If we are going to tweak
    > sprintf to make it suit our personal preferences, I'd rather see a
    > conversion character that behaved just like %f if given a good number, but
    > returned the empty string if given either an empty string or undef (rather
    > than converting it to zero and then applying %f to the zero.)
    >
    > > 0.1 :0.100
    > > 0.05 :0.050
    > > 0.03 :0.030
    > > 0.025 :0.025
    > > 0.02 :0.020
    > > 0.015 :0.015

    >
    > Apparently you want to preserve non-zero digits even if that means going
    > beyond 3 digits right of the decimal. But why did you stop at 4?
    >
    > 0.014999999999999999444888
    >
    > > 0.0125 :0.0125

    >
    >
    > 0.0125000000000000006938893
    >
    > How many consecutive zeros or nines are needed before you decide there are
    > enough to ignore what is the right of them?


    It appears to me the OP wants either 3 s.f. after the point or 3 places,
    whichever comes out shorter. Something like

    sub fmt {
    return
    map /(\d*\.\d{3}\d*?)0*$/,
    map /(\d*\.0*[1-9]\d\d)/,
    map { sprintf "%.308f", $_ }
    @_;
    }

    appears to work, but it's hardly pretty :(. The 308 is the number of
    places required to represent DBL_MIN with 53-bit doubles; if your perl
    is using 64-bit long doubles you will need 4932 instead.

    Ben
     
    Ben Morrow, Mar 31, 2008
    #8
  9. Ted Zlatanov Guest

    On Mon, 31 Mar 2008 21:55:16 +0100 Ben Morrow <> wrote:

    BM> It appears to me the OP wants either 3 s.f. after the point or 3 places,
    BM> whichever comes out shorter. Something like

    BM> sub fmt {
    BM> return
    BM> map /(\d*\.\d{3}\d*?)0*$/,
    BM> map /(\d*\.0*[1-9]\d\d)/,
    BM> map { sprintf "%.308f", $_ }
    BM> @_;
    BM> }

    BM> appears to work, but it's hardly pretty :(. The 308 is the number of
    BM> places required to represent DBL_MIN with 53-bit doubles; if your perl
    BM> is using 64-bit long doubles you will need 4932 instead.

    Is there any harm in always using 4932? I would guess not, except maybe
    for wasted CPU cycles.

    Ted
     
    Ted Zlatanov, Apr 1, 2008
    #9
  10. Dr.Ruud Guest

    Frank Seitz schreef:
    > Dr.Ruud:


    >> $ perl -wle'
    >> print "".reverse sprintf "%05.1f", "".reverse sprintf "%f", $_
    >> for qw/.1 .05 .03 .025 .02 .015 .0125 .01 .009 .00625 .005
    >> 1.987654321E1/
    >> '
    >> 0.100
    >> [...]
    >> 9.876543
    >>
    >> ;)

    >
    > And how do you deal with negative numbers and numbers >= 10? ;)


    Hey! There were only numbers in [0..1>, so I already extended it to
    [0..10>.

    Oh well,

    perl -wle'
    $n=length(int abs),
    print+($_<0?"-":"").reverse sprintf"%0*.*f",$n+4,$n,
    "".reverse sprintf"%f",abs
    for qw/0 .1 .05 .03 .025 .02 .015 .0125 .01 .009 .00625 .005
    1234567.89 -9876543.21/
    '
    0.000
    0.100
    0.050
    0.030
    0.025
    0.020
    0.015
    0.0125
    0.010
    0.009
    0.00625
    0.005
    1234567.890
    -9876543.210

    --
    Affijn, Ruud

    "Gewoon is een tijger."
     
    Dr.Ruud, Apr 2, 2008
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ian T

    zero pad a double

    Ian T, Feb 26, 2007, in forum: C Programming
    Replies:
    2
    Views:
    306
    Ian T
    Feb 26, 2007
  2. Matchless
    Replies:
    0
    Views:
    561
    Matchless
    Oct 11, 2008
  3. vasanth kumar
    Replies:
    1
    Views:
    120
    Evertjan.
    Oct 3, 2004
  4. PerlFAQ Server
    Replies:
    0
    Views:
    202
    PerlFAQ Server
    Feb 5, 2011
  5. PerlFAQ Server
    Replies:
    0
    Views:
    170
    PerlFAQ Server
    Mar 13, 2011
Loading...

Share This Page