in reply to Re^2: Decimal Floating Point (DFP) and does Perl needs DFP?
in thread Decimal Floating Point (DFP) and does Perl needs DFP?

would you mind stating the mathematically correct result (say, to six digits after decimal point)?

According to Math::Decimal128:
C:\>perl -MMath::Decimal128=":all" -le "$n1=Math::Decimal128->new('10' +, 0);$n2=Math::Decimal128->new('1000001', -6);for(1..60000000){$n1 *= + $n2}print $n1;" 114197313013072744502959647597176e-5
Or, to 6 decimal places: 1141973130130727445029596475.971760 which is the same as flexvault got.

With 80-bit long doubles, the calculation came out as:
C:\>perl -MMath::LongDouble=":all" -le "$n1=Math::LongDouble->new('10' +);$n2=Math::LongDouble->new('1.000001');for(1..60000000){$n1 *= $n2}p +rint $n1;" 1.14197313013239314e+027
Or, printing to 28 decimal digits (which implies a level of precision that we don't have):
C:\>perl -MMath::LongDouble=":all" -le "$n1=Math::LongDouble->new('10' +);$n2=Math::LongDouble->new('1.000001');for(1..60000000){$n1 *= $n2}p +rint LDtoSTRP($n1, 28);" 1.141973130132393144424071168e+027
This figure is equivalent to the first one you quoted.

With __float128:
C:\>perl -MMath::Float128=":all" -le "$n1=Math::Float128->new('10');$n +2=Math::Float128->new('1.000001');for(1..60000000){$n1 *= $n2}print $ +n1;" 1.14197313013072744502959647306684e+27
This differs from your second figure - and I don't think there's any valid reason that they should differ.
I'm inclined to think that mine is correct (surprise :-) because it matches up pretty well with the _Decimal128 calculation (where the respective precisions are reasonably close to each other).
Might you have assigned a long double or double value that got cast to a __float128, instead of assigning an actual __float128 value ?

As LanX points out, rounding is involved. The above one-liner programs all employ rounding to nearest with ties to even - the different results of course arising from the different precisions involved.

Cheers,
Rob

Replies are listed 'Best First'.
Re^4: Decimal Floating Point (DFP) and does Perl needs DFP?
by LanX (Saint) on Jan 19, 2015 at 01:44 UTC
    > rounding is involved.

    Calculating 10 * 1.000001 ** 6e7 should minimize the propagation of rounding errors, if exponentiation is sufficiently well implemented.

    Cheers Rolf

    PS: Je suis Charlie!

      Calculating 10 * 1.000001 ** 6e7 should minimize the propagation of rounding errors, if exponentiation is sufficiently well implemented.

      I have found a case where that's not so for the calculation in question - namely, Windows 7, perl-5.20.0, nvtype is double.
      But the same perl version and configuration on Ubuntu supports your assertion. So it might just be that the Windows exponentiation (or something else there) is buggy.
      I haven't experimented much at all, and don't really intend to.

      What's the reasoning behind your assertion ?

      Cheers,
      Rob
        > What's the reasoning behind your assertion ? 

        Exponentiation laws.

        E.g. x^10 = x^8 * x^2 and x^8 = ((x^2)^2)^2

        Just because 10 is 1010 binary, hence < 4*2 multiplications.

        6e7 should have a 26 bit representation so <52 multiplications needed.

        Of course there are even faster implementations which are less exact. I think that's what you are observing.

        edit
        Of course a binary calculation should be done with integer x=1000001 without fraction, dividing later thru 10^(6*60) should be easy enough.

        Cheers Rolf

        PS: Je suis Charlie!

        update

        proof of concept -> here

Re^4: Decimal Floating Point (DFP) and does Perl needs DFP?
by Anonymous Monk on Jan 19, 2015 at 18:55 UTC

    Right you are about the __float128 case. After rewriting the constant as (__float128)1000001 / 1e6, my result now matches your calculation.

    I'm inclined to think the bc-calculated value is accurate. But verifying that is rather laborious, for 1000001**6e7 is a number with ca 360M decimal digits.

      I'm inclined to think the bc-calculated value is accurate

      Yes, and the mpfr library agrees:
      C:\>perl -MMath::MPFR=":mpfr" -le "Rmpfr_set_default_prec(1000000); $x +=Math::MPFR->new('1.000001'); $x **= 60000000; $x *= 10; Rmpfr_out_st +r($x, 10,43,MPFR_RNDN); 1.141973130130727445029596475971653735685612e27
      That's calculated with a million bits of precision - and gives the same result as when calculated with a thousand bits of precision.
      So I think we can rest assured that that is the correct figure for 43 decimal digits.

      Cheers,
      Rob