Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Re: Variables are automatically rounded off in perl

by syphilis (Archbishop)
on Jul 21, 2016 at 07:35 UTC ( [id://1168208]=note: print w/replies, xml ) Need Help??


in reply to Variables are automatically rounded off in perl

Yes - I think this is generally considered to be a perl bug. (That's how I, at least, regard it.)
If perl's nvtype is 'double', perl will print floating point values rounded to 15 decimal digits - whereas the correct thing would be to round them to 17 decimal digits.
Hence the surprising result that you see.

Perl will correctly tell you that 3336.0 != 3335.9999999999995, yet will print both of those values identically (as 3336) ... which is rather absurd.

If you want to see the values rounded to 17 decimal digits then the best solution currently is to printf() 17 decimal digits - eg:
printf "%.16e\n", 3335.9999999999995;
Cheers,
Rob

Replies are listed 'Best First'.
Re^2: Variables are automatically rounded off in perl (humans)
by tye (Sage) on Jul 21, 2016 at 21:13 UTC

    It is not a bug that Perl rounds the display of numeric values to a number of digits that is fewer than the number of digits of precision that the internal floating point format achieves. It is an intentional feature due to the fact that you get even more complaints when a computation should yield 1/100 but the result gets displayed as "0.01000000000000002" (than the number of complaints for such not being "== 0.01").

    Over time there have been adjustments as to how much difference there should be between the precision of the local floating point format vs. precision of Perl's display of numbers. But the (non-zero) difference should remain.

    Wanting to see about 17 '9's or '0's near the end of a displayed number indicates a rather unrealistic expectation. 15 digits of accuracy is more than enough to notice that somebody misplaced a single grain of sand from your enormous beach. It is not important to inform a human that a single grain of sand was lost from the beach. The vast majority of situations are such that the loss of a single grain of sand from the beach is utterly insignificant. If you are in one of those rarefied situations where the exact number of grains of sand on your huge beach must not be off by even 1, then you shouldn't just be using mundane floating point.

    - tye        

      It is not a bug that Perl rounds the display of numeric values to a number of digits that is fewer than the number of digits of precision that the internal floating point format achieves

      It depends upon how you measure that "number of digits".
      Sure - if you allow more than 15 decimal digits then you lose the guarantee that different strings will assign different values. (It's possible that 2 different 16-digit strings will assign to the same value.)
      But there are a vast number of values that cannot be assigned if you restrict yourself to 15 decimal digits.
      To be able to assign each and every value you need 17 decimal digits, minimum.

      To me the sane thing is to have print() deliver a value that, when assigned back to a scalar, will result in the same value.

      I think the following is rather pathetic:
      C:\>perl -le "print sqrt(3);" 1.73205080756888 C:\>perl -le "print 'WTF' if 1.73205080756888 != sqrt(3);" WTF
      Why do we have to put up with that sort of anomaly when it could be eradicated by simply providing just *2* more digits of precision ?
      Is 17 decimal digits really that much more unreadable than 15 digits ?

      you get even more complaints when a computation should yield 1/100 but the result gets displayed as "0.01000000000000002"

      I don't think that's the right example.
      For me, I have to request 18 decimal digits of precision to get the trailing "2", and being surprised by that sort of result when more than 17 digits have been requested is a "user bug".
      The "correct" precision is 17 decimal digits - not 18.
      C:\>perl -le "printf '%.16e', 1/100" 1.0000000000000000e-002 C:\>perl -le "printf '%.17e', 1/100" 1.00000000000000002e-002
      A better example is:
      C:\>perl -le "printf '%.16e', 0.1" 1.0000000000000001e-001
      This happens because 0.10000000000000001 and 0.1 have the same internal floating point representation, and that representation is closer to 0.10000000000000001 than 0.1.
      I actually don't have any problem with that - but if we want to avoid such surprising results, there's a more refined way of dealing with this type of issue than simply getting the chainsaw out and hacking the tail off everything.

      I am told that python, for example, utilises this refinement.
      That is, python prints out 17 decimal digits but still prints 0.1 out as '0.1'.

      Update: Current bug report regarding this issue is here

      Cheers,
      Rob

        There is not only a single situation to consider. You present a situation where you want to preserve just slightly more precision than is preserved in that situation if you do nothing but the trivial to achieve your aims.

        C:\>perl -le "print 'WTF' if 1.00000000000000 != sqrt(3);" WTF

        Wow. If you are using '==' or '!=' on computed floating point values, then you've already lost my sympathy.

        I'm sorry, but the default, trivial way that a floating point value is displayed should not be optimized for "preserve every single bit of accuracy if you paste it back in and interpret it as a numeric value". It should be and is optimized for presenting the numeric value to humans.

        But there are a vast number of values that cannot be assigned if you restrict yourself to 15 decimal digits.

        To be clear, you can certainly assign 17 digits. Perl does not ignore beyond the 15th digit when you make an assignment (even when using a numeric literal).

        There are no shortage of easy, simple ways to preserve more accuracy if that is what you aim to do. printf and pack are the first two off the top of my head. Determining a sufficient number of digits to request from printf isn't even a difficult proposition.

        To me the sane thing is to have print() deliver a value that, when assigned back to a scalar, will result in the same value.

        To me, if you are lazily using the default string representation and just expecting 100% fidelity, then you aren't a very good programmer. To support that stance we'd have to make tabs be printed as \t and most sting values to be printed with quotes around them. Producing a representation that can preserve with perfect fidelity is simply not the purpose of print.

        During a recent period when the difference between stored accuracy and default displayed accuracy was less, we got tons of complaints because the result of code like:

        my $x = 0; for( 1..100 ) { $x += 0.01; # ... } print $x, $/;

        was not a nice "0.5" but "0.5000000000000002". Your plan would make it produce "0.50000000000000022".

        People just wanting to get a reasonable representation of a rather mundane value are who the behavior of a plain print should be catered to. People who can't stand miscounting one grain of sand on their huge beach are a much better choice for who needs to do a tiny bit of extra work.

        - tye        

        To me the sane thing is to have print() deliver a value that, when assigned back to a scalar, will result in the same value.

        I think the following is rather pathetic:

        C:\>perl -le "print sqrt(3);" 1.73205080756888 C:\>perl -le "print 'WTF' if 1.73205080756888 != sqrt(3);" WTF

        That should be expected for integer values, but for literal floating point values you would in general have to write them in a number base of a power of two if you want to express (and match) them exactly. In that sense print() cannot be of use to do the sane thing because information is already lost due to conversion to base ten (see commensurability).

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (6)
As of 2024-04-23 12:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found