I think that if there is a bug, which i'm not convinced of (see below),
it's likely to be int(), which may *first* be called by sprintf to cast
the floating-point number into an integral format ("%03d").

Indeed if you run :

        perl -e '$a=0.57; print int($a * 100)'

you get 0.56 .


Now, there must be an explanation for such an interesting behavior!
It may even have to do with the binary representation of floating-point numbers(FPN)
using the IEEE format, where 32bits FPN are represented
using  23 bits of mantissa.

The following script shows that 0.57 (as an example), an many others,
cannot be represented using 23 bits mantissa :

# this find the negative powers of 2 that should be added together
# to reach the goal (eg 0.57)
perl -e '       $goal = $ARGV[0];
                                $negpw= 1;
                                @l      = ();
                                $s      = 0;
                                foreach (1..23) {
                                        $a = $a/2;
                                        if ( ($s + $a) <= $goal){
                                                $s += $a;
                                                push @l, $_;
                                                print(sprintf("%0.30f  -  %03d\n", $s, 
$s * 100 ))
                                        }
                                };
                                print "@l"
                        ' 0.57

0.500000000000000000000000000000  -  050
0.562500000000000000000000000000  -  056
0.566406250000000000000000000000  -  056
0.568359375000000000000000000000  -  056
0.569335937500000000000000000000  -  056
0.569824218750000000000000000000  -  056
0.569946289062500000000000000000  -  056
0.569976806640625000000000000000  -  056
0.569992065429687500000000000000  -  056
0.569999694824218750000000000000  -  056
0.569999933242797851562500000000  -  056
1 4 8 9 10 11 13 15 16 17 22

i.e 0.1 + 0.0001 + 0.00000001 + 0.000000001
+ ...

You see in the result that 0.57 *cannot be* represented
as an  exact sum of negative powers of 2 within
23 bits.

From there, I guess any thing that happens is OK.

The problem of floating point representation,
and all the dillies that go with iti, is in fact
as old as computer science itself!

To solve your problem, use :

print(sprintf("%2.0f\n", $a * 100 ))

Hope this helps.

Franck


On Mon, 15 Apr 2002, Dominique Blas wrote:

> Sorry,
>
> I've found the following bug in mod_perl 1.25 and Perl 5.6.1.
> Maybe was it already released  but in case not here it is :
>
> perl -e '
> $a=0.57;
> print sprintf("%03d", $a * 100)'
>
> prints "056" instead of "057"
>
> Same behaviour with $a=0,58 that prints "057".
>
> Of course it works for other values and also if you write
>
> $a=0,57*100;
> print sprintf("%03d", $a);
>
>
> Bug in sprintf() ?
>
>
> Sincerely,
>
> db
>

-- 

Bonne réception,

Franck

====================================================
Essential Software - Ingénierie Informatique
Solutions Linux & Open Source en Polynésie française
----------------------------------------------------
http://www.esoft.pf/
Tél: (689) 56 23 95
====================================================

Reply via email to