Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > decimal round off issue

Reply
Thread Tools

decimal round off issue

 
 
Shiping Zhang
Guest
Posts: n/a
 
      09-22-2009
Is this a bug in perl?

$v = sprintf "%.1f", 2.25;
print $v, "\n";

The above code produced 2.2

$v = sprintf "%.1f", 2.35;
print $v, "\n";

The above code produced 2.4

I tested several versions, they all behaved the same.
 
Reply With Quote
 
 
 
 
J黵gen Exner
Guest
Posts: n/a
 
      09-22-2009
Shiping Zhang <(E-Mail Removed)> wrote:
>Is this a bug in perl?
>
>$v = sprintf "%.1f", 2.25;
>print $v, "\n";
>
>The above code produced 2.2


I cannot reproduce this observation. For me it prints 2.3.
( v5.10.0 built for MSWin32-x86-multi-thread)

>$v = sprintf "%.1f", 2.35;
>print $v, "\n";
>
>The above code produced 2.4
>
>I tested several versions, they all behaved the same.


However more than likely you don't even need the sprintf() assignment
with separate print(), a simple
printf "%.1f", 2.35;
will most likely behave exactly the same.

If so then try
printf "%.40f", 2.25;
and
printf "%.40f", 2.35;
on your Perl installation. This will most likely demonstrate the reason
for your observation. For an explanation please
- see "perldoc -q 999"
- re-read your notes from "Introduction into Computer Numerics"
- check the NG archives for dozens and dozens of similar posts and the
replies to them

jue
 
Reply With Quote
 
 
 
 
Shiping Zhang
Guest
Posts: n/a
 
      09-22-2009
On 9月22日, 下午1时08分, Shiping Zhang <(E-Mail Removed)> wrote:
> Is this a bug in perl?
>
> $v = sprintf "%.1f", 2.25;
> print $v, "\n";
>
> The above code produced 2.2
>
> $v = sprintf "%.1f", 2.35;
> print $v, "\n";
>
> The above code produced 2.4
>
> I tested several versions, they all behaved the same.


Okay, it's not a bug. This is due to limitation of machine (binary)
representation of floating point numbers. A test C program behaved
the same.
 
Reply With Quote
 
sln@netherlands.com
Guest
Posts: n/a
 
      09-22-2009
On Tue, 22 Sep 2009 12:52:36 -0700 (PDT), Shiping Zhang <(E-Mail Removed)> wrote:

>On 9月22日, 下午1时08分, Shiping Zhang <(E-Mail Removed)> wrote:
>> Is this a bug in perl?
>>
>> $v = sprintf "%.1f", 2.25;
>> print $v, "\n";
>>
>> The above code produced 2.2
>>
>> $v = sprintf "%.1f", 2.35;
>> print $v, "\n";
>>
>> The above code produced 2.4
>>
>> I tested several versions, they all behaved the same.

>
>Okay, it's not a bug. This is due to limitation of machine (binary)
>representation of floating point numbers. A test C program behaved
>the same.


Right, a binary thing! But more than that, different results across
different floating point hardware, firmware, libs.

You would think all things being equal, the same error pattern should
be had on all machines.

The good news is that internal fp operations wash out those discrepenccies
well past the number of digits of which the real universe can actually
be measured by physical means. Ie, its not right/wrong unless you can
prove it is/isn't. There are probably wider (bit-wise) floating point
registers available for calculations on scientific principles that can't
be proven.

c:\>perl -e "for(2.15,2.25,2.35,2.45,2.55,2.65) {$v = sprintf \"%.1f\", $_;
print \"$v\n\"}"
2.1
2.3
2.4
2.5
2.5
2.6

-sln
 
Reply With Quote
 
sln@netherlands.com
Guest
Posts: n/a
 
      09-23-2009
On Tue, 22 Sep 2009 14:42:09 -0700, John Stanley <(E-Mail Removed)> wrote:

>
>On Tue, 22 Sep 2009, Shiping Zhang wrote:
>
>> On 9?22?, ??1?08?, Shiping Zhang <(E-Mail Removed)> wrote:
>>> Is this a bug in perl?
>>>
>>> $v = sprintf "%.1f", 2.25;
>>> print $v, "\n";
>>>
>>> The above code produced 2.2
>>>...

>
>> Okay, it's not a bug. This is due to limitation of machine (binary)
>> representation of floating point numbers. A test C program behaved
>> the same.

>
>I don't think I missed class that day, but what binary representation of
>floating point CANNOT represent the base ten number "2.25"? That's 10.01
>base two.
>

Thats very true. And its non-repeating. Therefore, it should not be a
problem going from (1.001 x 2**1)base 2, to 2.25 base 10 and having it display
correctly when it comes to rounding and formatting string representation.
I'm not sure that rounding happens the same way on all systems when there is
a repeting binary fraction (like .55 base 10).

From wikipedia: http://en.wikipedia.org/wiki/IEEE_754-1985

I wonder if you do a bitwise examination of a float variable if it
will show the sign, exp, fraction bits like in the standard?
Or on the language level, are the bitwise operators restricted to
operations on integers?

Where are the calculators that do binary <-> decimal fractions?
Don't want to do it by hand all the time.

-sln



 
Reply With Quote
 
Josef Moellers
Guest
Posts: n/a
 
      09-23-2009
J黵gen Exner wrote:
> Shiping Zhang <(E-Mail Removed)> wrote:
>> Is this a bug in perl?
>>
>> $v = sprintf "%.1f", 2.25;
>> print $v, "\n";
>>
>> The above code produced 2.2

>
> I cannot reproduce this observation. For me it prints 2.3.
> ( v5.10.0 built for MSWin32-x86-multi-thread)


v5.8,8 running on Kubuntu 8.04LTS has the same peculiarity:

$v = sprintf "%.1f", 2.25;
print $v, "\n";
$v = sprintf "%.1f", 2.35;
print $v, "\n";

2.2
2.4

--
These are my personal views and not those of Fujitsu Technology Solutions!
Josef M鰈lers (Pinguinpfleger bei FTS)
If failure had no penalty success would not be a prize (T. Pratchett)
Company Details: http://de.ts.fujitsu.com/imprint.html
 
Reply With Quote
 
Peter J. Holzer
Guest
Posts: n/a
 
      09-23-2009
On 2009-09-22 17:34, J黵gen Exner <(E-Mail Removed)> wrote:
> Shiping Zhang <(E-Mail Removed)> wrote:
>>Is this a bug in perl?
>>
>>$v = sprintf "%.1f", 2.25;
>>print $v, "\n";
>>
>>The above code produced 2.2

>
> I cannot reproduce this observation. For me it prints 2.3.
> ( v5.10.0 built for MSWin32-x86-multi-thread)


Strange. It should produce 2.2 (2.25 is exactly halfway between 2.2 and
2.3, so the "round to even" rule is used). However, 2.2 and 2.3 aren't
exactly representable, so maybe that's where the rounding error is.

On Debian Linux (perl, v5.10.0 built for i486-linux-gnu-thread-multi),
this:

perl -e 'for(2.15,2.25,2.35,2.45,2.55,2.65, 2.75, 2.85, 2.95) {printf "%.60f %.1f\n", $_, $_ }'

prints:

2.149999999999999911182158029987476766109466552734 375000000000 2.1
2.250000000000000000000000000000000000000000000000 000000000000 2.2
2.350000000000000088817841970012523233890533447265 625000000000 2.4
2.450000000000000177635683940025046467781066894531 250000000000 2.5
2.549999999999999822364316059974953532218933105468 750000000000 2.5
2.649999999999999911182158029987476766109466552734 375000000000 2.6
2.750000000000000000000000000000000000000000000000 000000000000 2.8
2.850000000000000088817841970012523233890533447265 625000000000 2.9
2.950000000000000177635683940025046467781066894531 250000000000 3.0

which is exactly correct: The values which are slightly above or below
0.x5 are rounded up or down as appropriate, and 2.25 and 2.75 are
rounded to even.

hp

 
Reply With Quote
 
sln@netherlands.com
Guest
Posts: n/a
 
      09-23-2009
On Wed, 23 Sep 2009 19:21:08 +0200, "Peter J. Holzer" <(E-Mail Removed)> wrote:

>On 2009-09-22 17:34, J黵gen Exner <(E-Mail Removed)> wrote:
>> Shiping Zhang <(E-Mail Removed)> wrote:
>>>Is this a bug in perl?
>>>
>>>$v = sprintf "%.1f", 2.25;
>>>print $v, "\n";
>>>
>>>The above code produced 2.2

>>
>> I cannot reproduce this observation. For me it prints 2.3.
>> ( v5.10.0 built for MSWin32-x86-multi-thread)

>
>Strange. It should produce 2.2 (2.25 is exactly halfway between 2.2 and
>2.3, so the "round to even" rule is used). However, 2.2 and 2.3 aren't
>exactly representable, so maybe that's where the rounding error is.
>
>On Debian Linux (perl, v5.10.0 built for i486-linux-gnu-thread-multi),
>this:
>
>perl -e 'for(2.15,2.25,2.35,2.45,2.55,2.65, 2.75, 2.85, 2.95) {printf "%.60f %.1f\n", $_, $_ }'
>
>prints:
>
>2.14999999999999991118215802998747676610946655273 4375000000000 2.1
>2.25000000000000000000000000000000000000000000000 0000000000000 2.2
>2.35000000000000008881784197001252323389053344726 5625000000000 2.4
>2.45000000000000017763568394002504646778106689453 1250000000000 2.5
>2.54999999999999982236431605997495353221893310546 8750000000000 2.5
>2.64999999999999991118215802998747676610946655273 4375000000000 2.6
>2.75000000000000000000000000000000000000000000000 0000000000000 2.8
>2.85000000000000008881784197001252323389053344726 5625000000000 2.9
>2.95000000000000017763568394002504646778106689453 1250000000000 3.0
>
>which is exactly correct: The values which are slightly above or below
>0.x5 are rounded up or down as appropriate, and 2.25 and 2.75 are
>rounded to even.
>
> hp


I never heard of that "round to even" rule. On my build it rounds "up"
all the time. Maybe I don't have the latest build.

perl -e "for(2.15,2.25,2.35,2.45,2.55,2.65, 2.75, 2.85, 2.95) {printf \"%.60f %.1f\n\", $_, $_ }"

2.149999999999999900000000000000000000000000000000 000000000000 2.1
2.250000000000000000000000000000000000000000000000 000000000000 2.3
2.350000000000000100000000000000000000000000000000 000000000000 2.4
2.450000000000000200000000000000000000000000000000 000000000000 2.5
2.549999999999999800000000000000000000000000000000 000000000000 2.5
2.649999999999999900000000000000000000000000000000 000000000000 2.6
2.750000000000000000000000000000000000000000000000 000000000000 2.8
2.850000000000000100000000000000000000000000000000 000000000000 2.9
2.950000000000000200000000000000000000000000000000 000000000000 3.0

I'm sure this is a result of a define flag passed via compiler option.
I' got the active state 5.10 built using gcc. I looked over the build
parameters using perl -V. I've only used MS compilers, so I don't know
some of the options listed. I looked for optimizations that I recognized,
only saw O2, compile for speed. MS has some /FP: optimizations like
precise/strict,etc.., that gcc doesen't.
Gcc looks like it has nvtype as double, its size 64 bit.
----------------
v5.10.0 built for MSWin32-x86-multi-thread
(with 5 registered patches)

Binary build 1004 [287188] provided by ActiveState http://www.ActiveState.com
Built Sep 3 2008 13:16:37
--------------

-sln
 
Reply With Quote
 
Peter J. Holzer
Guest
Posts: n/a
 
      09-23-2009
On 2009-09-23 19:21, http://www.velocityreviews.com/forums/(E-Mail Removed) <(E-Mail Removed)> wrote:
> On Wed, 23 Sep 2009 19:21:08 +0200, "Peter J. Holzer" <(E-Mail Removed)> wrote:
>>On 2009-09-22 17:34, J黵gen Exner <(E-Mail Removed)> wrote:
>>> Shiping Zhang <(E-Mail Removed)> wrote:
>>>>Is this a bug in perl?
>>>>
>>>>$v = sprintf "%.1f", 2.25;
>>>>print $v, "\n";
>>>>
>>>>The above code produced 2.2
>>>
>>> I cannot reproduce this observation. For me it prints 2.3.
>>> ( v5.10.0 built for MSWin32-x86-multi-thread)

>>
>>Strange. It should produce 2.2 (2.25 is exactly halfway between 2.2 and
>>2.3, so the "round to even" rule is used). However, 2.2 and 2.3 aren't
>>exactly representable, so maybe that's where the rounding error is.
>>
>>On Debian Linux (perl, v5.10.0 built for i486-linux-gnu-thread-multi),
>>this:
>>
>>perl -e 'for(2.15,2.25,2.35,2.45,2.55,2.65, 2.75, 2.85, 2.95) {printf "%.60f %.1f\n", $_, $_ }'
>>
>>prints:
>>
>>2.1499999999999999111821580299874767661094665527 34375000000000 2.1
>>2.2500000000000000000000000000000000000000000000 00000000000000 2.2
>>2.3500000000000000888178419700125232338905334472 65625000000000 2.4
>>2.4500000000000001776356839400250464677810668945 31250000000000 2.5
>>2.5499999999999998223643160599749535322189331054 68750000000000 2.5
>>2.6499999999999999111821580299874767661094665527 34375000000000 2.6
>>2.7500000000000000000000000000000000000000000000 00000000000000 2.8
>>2.8500000000000000888178419700125232338905334472 65625000000000 2.9
>>2.9500000000000001776356839400250464677810668945 31250000000000 3.0
>>
>>which is exactly correct: The values which are slightly above or below
>>0.x5 are rounded up or down as appropriate, and 2.25 and 2.75 are
>>rounded to even.

>
> I never heard of that "round to even" rule.


It is mentioned in this group just about every time that rounding is
discussed, which is probably at least once or twice per year.

The rule was used at least since the early 20th century (Wikipedia cites
a book from 1906). In IEEE-754 arithmetic (which is used in all current
FP units) it is the default rounding mode.

> On my build it rounds "up"
> all the time. Maybe I don't have the latest build.
>
> perl -e "for(2.15,2.25,2.35,2.45,2.55,2.65, 2.75, 2.85, 2.95) {printf \"%.60f %.1f\n\", $_, $_ }"
>
> 2.149999999999999900000000000000000000000000000000 000000000000 2.1
> 2.250000000000000000000000000000000000000000000000 000000000000 2.3
> 2.350000000000000100000000000000000000000000000000 000000000000 2.4
> 2.450000000000000200000000000000000000000000000000 000000000000 2.5
> 2.549999999999999800000000000000000000000000000000 000000000000 2.5
> 2.649999999999999900000000000000000000000000000000 000000000000 2.6
> 2.750000000000000000000000000000000000000000000000 000000000000 2.8
> 2.850000000000000100000000000000000000000000000000 000000000000 2.9
> 2.950000000000000200000000000000000000000000000000 000000000000 3.0
>
> I'm sure this is a result of a define flag passed via compiler option.


More likely it's caused by the implementation of sprintf in the C
library.

> I' got the active state 5.10 built using gcc. I looked over the build
> parameters using perl -V.


Is there a "standard" C library on Windows which gcc has to use or does
it use the glibc? I suspect it's the former (I've seen similar results
with Microsofts C compiler).

hp
 
Reply With Quote
 
Ilya Zakharevich
Guest
Posts: n/a
 
      09-24-2009
On 2009-09-24, Ben Morrow <(E-Mail Removed)> wrote:
> Huh? glibc is Linux- (well, and Hurd-) only.


Last time I compiled glibc was several years ago. But it was nowhere
close to Linux and/or Hurd. It is just a C library on top of POSIX -
at lest at was at the time...

> gcc on Win32 uses MSVCRT.DLL,


AFAIK, there are many gcc's on Win32, all (?) using different CRTL...

Yours,
Ilya
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: round off to two decimal & return float 喈嗋喈距畾喁嵿畾喁 Python 1 03-30-2013 01:36 PM
Re: round off to two decimal & return float Peter Otten Python 0 03-30-2013 09:44 AM
round off to two decimal & return float 喈嗋喈距畾喁嵿畾喁 Python 2 03-30-2013 09:30 AM
How to truncate/round-off decimal numbers? Girish Sahani Python 15 12-17-2011 01:06 AM
how to round off decimal point arianne75 General Computer Support 0 06-08-2007 06:17 AM



Advertisments