Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Round a fraction

by fglock (Vicar)
on Aug 02, 2002 at 12:52 UTC ( [id://187072]=perlquestion: print w/replies, xml ) Need Help??

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

I'm trying to find a better way to round the last digit of some fractional numbers.

All my numbers match this:        /^0\.\d{5,}9{3}\d$/

The numbers will always be rounded "up" (like in POSIX::ceil, but in a fractional context).

0.123499999996 rounds to 0.1235 0.12345678999994 rounds to 0.12345679

This is what I have so far: (adds 0.00000000000006 to 0.12345678999994 giving 0.12345679)

if ($frac =~ /999.$/) { my ($zeroes, $digit) = $frac =~ /\.(.*)(.)$/; $digit = '0.' . '0' x (length($zeroes)-1) . sprintf("%02d", 10 - $digit); $frac += $digit; }

Replies are listed 'Best First'.
How do you ++ a fraction?
by fglock (Vicar) on Aug 02, 2002 at 13:30 UTC

    How do you "add 1" to last digit of a fraction such that

         0.0012 gives  0.0013

         0.99999 gives  1

    Update: rephrased question

      sub incdec { $number = shift; # do something if not /^\d*\.\d+$/ return $number+1 if $number =~ /^\d+$/; $number =~ /\.(\d+)$/; return $number + ("1E-".length($1); } for $n (1, .004, 1.99, 1.79, 1.009999) { print "$n++ = ".incdec($n)."\n"; }

      gives:

      1++ = 2 0.004++ = 0.005 1.99++ = 2 1.79++ = 1.8 1.009999++ = 1.01

      Update: use E notation

      --
      Steve Marvell

        Thanks.

          (0.1 ** length($1)) could also be written:
         ("1E-" . length($1))

        update: This is what I came up with:

        $frac = shift; $frac =~ s/(\d+).$/$1/; # remove last digit & get fraction size $frac += "1E-" . length($1); # add 1E-(size) => 0.0001 print $frac;

        Works for "0.123999", "10.12399" and ".12399"

        The result is weird when the number does not have a fractional part, but that is not my case.

        Don't reinvoke on the same variable...

        (1++) ++ = 3 (0.004++) ++ = 0.006
        But...
        (1.99++) ++ = 3 (1.79++) ++ = 1.9 (1.009999++) ++ = 1.02

        --
        Tommy
        Too stupid to live.
        Too stubborn to die.

Re: Round a fraction
by frankus (Priest) on Aug 02, 2002 at 14:45 UTC
    Okay, I am definitely missing something here...

    If not, why not just use sprintf

    like perl -e 'printf("%0.5f",1.233394494955);
    So what did I miss?

    --

    Brother Frankus.

    ¤

      I want to round a number, keeping as many digits as possible, if the number ends in /999.$/ .

      So I'd need something like a "%0.(max)f" format (maybe it exists?)

Re: Round a fraction
by talexb (Chancellor) on Aug 02, 2002 at 12:58 UTC
    In the regexp I'd just look for
    • an arbitrarily long string of zeroes and chop them off starting with the first one and
    • an arbitrarily long strong of nines and chop them off starting with the first one, then add one to the end of the remaining number to make it round up.
    By handling rounding in both directions you save yourself some trouble later on.

    You didn't say, was it necessary to retain the tiny amount that you adjusted by? My suggestion doesn't keep that information -- I assumed it was irrelevant.

    --t. alex

    "Mud, mud, glorious mud. Nothing quite like it for cooling the blood!"
    --Michael Flanders and Donald Swann

      was it necessary to retain the tiny amount that you adjusted by?

      No, that is just some quick hack.

      add one to the end

      Is there an easy way to do that? (besides using substr and x)

Re: Round a fraction
by mojotoad (Monsignor) on Aug 02, 2002 at 20:04 UTC
    I'm curious as to why you want to do this? If you're doing any sort of real calculations with the numbers (or to calculate them) then you should have some sort of idea of the number of significant figures you're dealing with from the original source.

    Otherwise, I'm guessing this is just for aesthetics of presentation? I guess I'm just too steeped in scientific ambivalence when it comes to the beauty of numbers. I'd just pick either the number of sig figs you want to use, or the number of decimal places, and use sprintf.

    This is not criticism -- I am curious as to what you want to do with your numbers.

    Matt

Re: Round a fraction
by thelenm (Vicar) on Aug 02, 2002 at 15:49 UTC
    The Math::BigFloat module may be of some use to you.

    -- Mike

    --
    just,my${.02}

Re: Round a fraction
by fglock (Vicar) on Aug 02, 2002 at 17:10 UTC

    Found a way to round it safely:

    my $frac = shift; if ($frac =~ /\..{5,}000.$/) { $frac =~ s/.$//; } elsif ($frac =~ /(\..{5,}999)(.)$/) { $frac = $frac + ( (10-$2) . "E-" . length($1)); } print "rounded to $frac";

    note: $frac can be an integer; $frac must be positive

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (7)
As of 2024-03-28 11:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found