Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Perl 5 numeric type and simplifications

by pango (Initiate)
on May 05, 2021 at 01:42 UTC ( [id://11132051]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks,

I have a question regarding Perl's numeric type, and how (I assume) it simplifies the value before storing/printing them.

For example:

use warnings; my $foo = 50.0; warn $foo;

would display 50, rather than 50.0. I'm interested in knowing if this is always the case (can I rely on this behaviour of simplifying the number?), where can I read more about this if it is documented. I tried searching for more information in https://perldoc.perl.org/perlnumber but I couldn't find anything specific to this.

I am only interested because I find this an easy way to remove trailing decimal zeroes, and if I can get away with not using sprintf then that would be great.

Replies are listed 'Best First'.
Re: Perl 5 numeric type and simplifications
by haukex (Archbishop) on May 05, 2021 at 05:41 UTC
    I'm interested in knowing if this is always the case (can I rely on this behaviour of simplifying the number?)

    The Perl Cookbook says "When Perl is told to print a floating-point number but not told the precision, it automatically rounds that number to however many decimal digits of precision that your machine supports." So when you state the question so generally, then I would say that I wouldn't rely on it, and I would use e.g. int or sprintf (or, if you wanted to trade precision for performance, bignum). See also What Every Programmer Should Know About Floating-Point Arithmetic.

Re: Perl 5 numeric type and simplifications
by syphilis (Archbishop) on May 05, 2021 at 09:50 UTC
    can I rely on this behaviour of simplifying the number?)

    Perl's print() function does indeed like to "simplify" numbers, often to an embarrassingly absurd extent.
    Here, we see three unequal numbers printed identically:
    C:\>perl -e "$x = 1.23456789012345e15; print $x;" 1.23456789012345e+15 C:\>perl -e "$x = 1.234567890123454e15; print $x;" 1.23456789012345e+15 C:\>perl -e "$x = 1.2345678901234544e15; print $x;" 1.23456789012345e+15
    Perl knows that all 3 values are different:
    C:\>perl -e "print 'different' if 1.23456789012345e15 != 1.23456789012 +3454e15;" different C:\>perl -e "print 'different' if 1.23456789012345e15 != 1.23456789012 +34544e15;" different C:\>perl -e "print 'different' if 1.234567890123454e15 != 1.2345678901 +234544e15;" different
    yet happily presents them as identical.
    You can't really rely on perl's print() for anything much when floating point values are concerned.

    Cheers,
    Rob
Re: Perl 5 numeric type and simplifications
by Discipulus (Canon) on May 05, 2021 at 06:47 UTC
    Hello pango and welcome to the monastery and to the wonderful world of Perl!

    You already got the correct answer, so apart my welcome, I only want to comment:

    > I am only interested because I find this an easy way to remove trailing decimal zeroes, and if I can get away with not using sprintf then that would be great.

    you dont pay CPU cycles nor characters in your program, do you? So it is better to embrace the more idiomatic style you can, without relying on edge cases to accomplish simple tasks as the precision of a number. One of our wise brothers has in their signature: Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond and even if in Perl there are many way to get the job done I suggest you to write your programs in the clearest form you can get.

    Another great motto goes like: Being debugging twice harder than programming, dont program at your best as you dont be able to debug it, by definition

    Imagine a weird bug in your 5k lines of perl code spread among different modules, a bug due to a weak assumption on perl rounding beahviour... good luck :)

    Explore edge cases, try everything, but when you write something intended to be usable and durable choose the plainest way.

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
      Imagine a weird bug in your 5k lines of perl code spread among different modules...

      I have experienced this kind of bug, or perhaps strange behaviour would be a better term, very recently. In the past I have almost always passed the current user to the database to do the figuring out what to do. But as now all code is being written with Template thanks to the wisdom and good influence of the Monastery, more recently I have wanted the Template to do the work. I couldn't figure out why this wasn't working:

      [% IF user.idUser == current_user %]<input type="button" onClick="doSo +mething();">[% END %]
      Until I printed out current_user from within Template to find it was left padded to 8 digits! MySQL queries treat 255 = 00000255 as true whereas Template treats [% 255 == 00000255 %] as false! I got around the issue by adding zero to the current user before passing it to the Template. I have no idea why the user is calculated and padded this way but too much other code relies on them that I dare not attempt to change this.

Re: Perl 5 numeric type and simplifications
by BillKSmith (Monsignor) on May 06, 2021 at 03:55 UTC
    The choice between print and printf depends on how badly you 'rely' on the format. The former usually does what you want with less effort. It may even be better for a special case that you forgot about. An occasional 'long number' may be annoying, but does no real harm if you are calculating the next move in your fantasy football game. In another application, the same behavior could spoil a whole batch of expensive forms (or worse). Clearly the latter is called for. They each have advantages. It is part of a Perl programmer's job to choose appropriately for each application.
    Bill
Re: Perl 5 numeric type and simplifications (updated)
by LanX (Saint) on May 07, 2021 at 00:39 UTC
      ... even if it's internal representation is flawed

      It would be better to instead say "even if it's internal representation is rounded." Rounding is not a flaw - unless, of course, the rounding was done in an incorrect manner.

      ... part of arithmetic operations which accumulated rounding errors

      Similarly, I would rewrite that as (something like) "part of arithmetic operations which were rounded".

      Just to be clear - both "flawed" internal representations and "rounding errors" are very rare in perl. I think both of those phrases should be reserved to apply to cases where rounding has been done incorrectly.
      If those errors are encountered in perl-5.30.0 or later then I'd recommend reporting them.

      On USE_QUADMATH builds of perl, some sqrt() operations round incorrectly (by one unit of least precision). And, with USE_LONGDOUBLE builds of perl on Windows there's a specific range of values that don't assign correctly.
      There's also some BSD and Solaris (and perhaps other) systems around that have some pretty weird rules regarding USE_LONGDOUBLE arithmetic. (I think that they are "flawed", though it might be arguable.)
      Offhand, I struggle to recall there being any flawed internal representations or rounding errors on perl-5.30 or later when perl's NV is "double".

      Cheers,
      Rob
        Did I say it's a Perl problem?

        I learned the terms "rounding error" and "accumulated rounding error" in CS classes at university for these effects. °

        To be sure it's not a translation problem, I searched and found (among many others) this English Wikipedia article

        > Rounding error

        A roundoff error, also called rounding error, is the difference between the result produced by a given algorithm using exact arithmetic and the result produced by the same algorithm using finite-precision, rounded arithmetic.

        Rounding errors are due to inexactness in the representation of real numbers and the arithmetic operations done with them.

        So what exactly is your problem now?

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

        update

        °) actually I think I already learned it in school in physics classes. The concept is older than CS. I suppose it was introduced a century earlier by Carl Friedrich Gauß.

        What Every Computer Scientist Should Know About Floating-Point Arithmetic

        • Rounding Error
        ... given any fixed number of bits, most calculations with real numbers will produce quantities that cannot be exactly represented using that many bits. Therefore the result of a floating-point calculation must often be rounded in order to fit back into its finite representation. This rounding error is the characteristic feature of floating-point computation. ...

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

Re: Perl 5 numeric type and simplifications
by perlfan (Vicar) on May 06, 2021 at 06:59 UTC
      This site is quite useful, it shows exactly what bits etc. each floating point number corresponds to. There is also an article.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (5)
As of 2024-03-28 15:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found