Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

Well, you got rather quiet on the subject but I wasn't convinced that there might not be some truth to the "rounding mode" stuff. But it turns out that there was no truth to it at all for this case.

The rounding mode is already at NEAR and the rounding mode makes no difference in the behavior of sprintf()'s rounding. The reason you got results more to your liking is purely due to computing 0.000035 using repeated additions rather than using the constant 0.000035 directly.

Here is how I modified your test code to prove this:

#!/usr/bin/perl -lw use strict; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'END_C', NAME => 'ieeroundmode', CLEAN_AFTER_BUILD +=> 0; unsigned int controlFP( unsigned int new, unsigned int mask ) { return _controlfp( new, mask ); } END_C use constant { RC_MASK => 0x00000300, RC_CHOP => 0x00000300, RC_UP => 0x00000200, RC_DOWN => 0x00000100, RC_NEAR => 0x00000000, }; my @n; my $m; @n = qw< 0.000005 0.000015 0.000025 0.000035 0.000045 0.000055 0.000065 0.000075 0.000085 0.000095 >; $m= $n[0]; for my $n ( @n ) { printf " %.22f %.5f %.22f %.5f\n", $n, $n, $m, $m; $m += 0.00001; } print "Setting mode CHOP; controlFP returned: ", controlFP( RC_CHOP, R +C_MASK ); @n = qw< 0.000005 0.000015 0.000025 0.000035 0.000045 0.000055 0.000065 0.000075 0.000085 0.000095 >; $m= $n[0]; for my $n ( @n ) { printf " %.22f %.5f %.22f %.5f\n", $n, $n, $m, $m; $m += 0.00001; } print "Setting mode UP; controlFP returned: ", controlFP( RC_UP, RC_MA +SK ); @n = qw< 0.000005 0.000015 0.000025 0.000035 0.000045 0.000055 0.000065 0.000075 0.000085 0.000095 >; $m= $n[0]; for my $n ( @n ) { printf " %.22f %.5f %.22f %.5f\n", $n, $n, $m, $m; $m += 0.00001; } print "Setting mode DOWN; controlFP returned: ", controlFP( RC_DOWN, R +C_MASK ); @n = qw< 0.000005 0.000015 0.000025 0.000035 0.000045 0.000055 0.000065 0.000075 0.000085 0.000095 >; $m= $n[0]; for my $n ( @n ) { printf " %.22f %.5f %.22f %.5f\n", $n, $n, $m, $m; $m += 0.00001; } print "Setting mode NEAR; controlFP returned: ", controlFP( RC_NEAR, R +C_MASK ); @n = qw< 0.000005 0.000015 0.000025 0.000035 0.000045 0.000055 0.000065 0.000075 0.000085 0.000095 >; $m= $n[0]; for my $n ( @n ) { printf " %.22f %.5f %.22f %.5f\n", $n, $n, $m, $m; $m += 0.00001; }

And here is summarized output, collapsing identical sections and highlighting the differences between the different parts:

Default / NEAR (compare computed value with cons +tant) 0.0000050000000000000004 0.00001 =0.0000050000000000000004= =0.000 +01= 0.0000150000000000000000 0.00002 <0.0000150000000000000020> =0.000 +02= 0.0000250000000000000010 0.00003 <0.0000250000000000000050> =0.000 +03= 0.0000349999999999999970 0.00003 <0.0000350000000000000040> <0.000 +04> 0.0000450000000000000030 0.00005 =0.0000450000000000000030= =0.000 +05= 0.0000550000000000000020 0.00006 =0.0000550000000000000020= =0.000 +06= 0.0000649999999999999940 0.00006 <0.0000650000000000000080> <0.000 +07> 0.0000749999999999999930 0.00007 <0.0000750000000000000070> <0.000 +08> 0.0000850000000000000060 0.00009 =0.0000850000000000000060= =0.000 +09= 0.0000950000000000000050 0.00010 =0.0000950000000000000050= =0.000 +10= CHOP / DOWN (compare value to Default / NEAR case) >0.0000049999999999999996< >0.00000< >0.0000049999999999999996< >0.000 +00< >0.0000149999999999999990< >0.00001< >0.0000150000000000000000< =0.000 +02= >0.0000249999999999999980< >0.00002< >0.0000250000000000000010< =0.000 +03= =0.0000349999999999999970= =0.00003= >0.0000349999999999999970< >0.000 +03< >0.0000449999999999999960< >0.00004< >0.0000449999999999999960< >0.000 +04< >0.0000549999999999999950< >0.00005< >0.0000549999999999999950< >0.000 +05< >0.0000649999999999999940< >0.00006< >0.0000649999999999999940< >0.000 +06< =0.0000749999999999999930= >0.00007< >0.0000749999999999999930< >0.000 +07< >0.0000849999999999999930< >0.00008< >0.0000849999999999999930< >0.000 +08< >0.0000949999999999999920< >0.00009< >0.0000949999999999999920< >0.000 +09< UP (compare value to Default / NEAR case) =0.0000050000000000000004= =0.00001= =0.0000050000000000000004= =0.000 +01= =0.0000150000000000000000= =0.00002= =0.0000150000000000000020= =0.000 +02= =0.0000250000000000000010= =0.00003= =0.0000250000000000000050> =0.000 +03= <0.0000350000000000000040> <0.00004> <0.0000350000000000000100> =0.000 +04= =0.0000450000000000000030= =0.00005= <0.0000450000000000000160> =0.000 +05= =0.0000550000000000000020= =0.00006= <0.0000550000000000000220> =0.000 +06= <0.0000650000000000000080> <0.00007> <0.0000650000000000000350> =0.000 +07= <0.0000750000000000000070> <0.00008> <0.0000750000000000000480> =0.000 +08= =0.0000850000000000000060= =0.00009= <0.0000850000000000000600> =0.000 +09= =0.0000950000000000000050= =0.00010= <0.0000950000000000000730> =0.000 +10=

Setting rounding mode to NEAR gives the exact same results as I get before changing the rounding mode. Setting it to UP gives the desired results (for my code) not because it changes how sprintf rounds but because it changes how Perl converts the string '0.000035' into a floating point value, ensuring that the result is always slightly higher than (or equal to) the value that the string represents. But using UP also introduces growing inaccuracy in the additions.

The "better" results in your NEAR case were only the luck of 0.000005 and 0.000010 converting to floating point values slightly larger than the numbers those strings represent.

Also note that your results would be slightly different than mine for the DOWN / CHOP cases, since you put the constant 0.000005 in as a number so that it was interpreted at compile time (and thus using the NEAR rounding mode) rather than the way I used strings to force run-time interpretation of the constants using the different round modes (except for 0.000010).

- tye        


In reply to Re^2: RFC: Large Floating Point Numbers - Rounding Errors (absolutely not rounding mode) by tye
in thread RFC: Large Floating Point Numbers - Rounding Errors by GAVollink

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2024-04-25 07:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found