Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

cos (100000000.0)

by kavehmz (Initiate)
on Sep 01, 2009 at 14:11 UTC ( #792659=perlquestion: print w/ replies, xml ) Need Help??
kavehmz has asked for the wisdom of the Perl Monks concerning the following question:

I have these results from several languages all in Intel x86 machine

C++ std math.h cos(100000000.0): -0.363385
Java cos(100000000.0) :-0.3633850893556905
Perl cos (100000000.0):-0.36338508935581

why Perl is returning last digits wrong, and why it does not truncate it to what it knows it is the last precision it can correctly calculate?

Comment on cos (100000000.0)
Re: cos (100000000.0)
by moritz (Cardinal) on Sep 01, 2009 at 14:14 UTC
    It seems to be just a normal floating point error.
    and why it does not truncate it to what it knows it is the last precision it can correctly calculate?

    To know how many digits it can calculate correctly it would have to track rounding errors, resulting a large performance penalty. So it doesn't do that, and neither does C++ or Java.

    C++ just uses a much more defensive default precision.

    Perl 6 - links to (nearly) everything that is Perl 6.
Re: cos (100000000.0)
by ikegami (Pope) on Sep 01, 2009 at 14:25 UTC

    Two comments.

    • First, I get the same answer as Java:

      $ perl -le'print cos(100000000)' -0.363385089355691 $ perl -e'printf "%.16g\n", cos(100000000)' -0.3633850893556905

      The underlying C library makes a difference.

    • Second, floating point numbers don't have a precision field. Assuming it's even possible, accommodating such a field would require a substantial drop in max precision. You are free to track such data yourself, however.

      Maybe you answer is different from mine because you are running Perl in another architecture. Are you using a Intel based machine?
      And how can I decide, up to what point I can trust Perl calculations?

      Becasue it is a different situation that we have intrinsic error in floating point numbers like
      http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

      For that kind of expected problems i am ready to check my values properly.

      But for what I get from a call to a language function why should it be careful that it will return a wrong number?

      Is there a way that I restrict Perl return values to what is safe for big number without truncating all return numbers from native Perl functions by myself?
      And when Perl is returning numbers in this fashion can I be sure that if I use bigger numbers, the error wont grow to make more wrong digits?

        Maybe you answer is different from mine because you are running Perl in another architecture. Are you using a Intel based machine?

        I've already said it's the underlying C library that makes the difference for cos().

        And how can I decide, up to what point I can trust Perl calculations?

        It's my understanding that libraries often approximate the result of trig functions. In Perl's case, it uses the underlying C library. I don't know what kind of precision guarantees (if any) C makes concerning its trig functions. Feel free to look it up.

        And when Perl is returning numbers in this fashion can I be sure that if I use bigger numbers, the error wont grow to make more wrong digits?

        I don't understand the question. You single out the previously discussed manner or returning numbers, but no ways of returning numbers were previously discussed. What does Perl returning numbers even mean? What are the other manners in which Perl returns numbers to which you allude?

        Is there a way that I restrict Perl return values to what is safe for big number without truncating all return numbers from native Perl functions by myself?

        The premise makes no sense. Truncating and rounding reduce precision.

        Actual: -0.3633850893556905538... Java's error: 0.0000000000000000538... Your C's error: 0.0000000000001194462... Rounded error: 0.0000000000003094462... Truncated error: 0.0000000000006905538...

        Besides that, the precision of the result of each operation depends on the precision of the result of each operand of that operation. Neither Perl nor the computer know the precision of the operands, so it can't know the precision of the output.

        Maybe you answer is different from mine because you are running Perl in another architecture.

        I am running perl in a different architecture (amd64), and I get the same result as you for perl:
        C:\_32>perl -e "print cos(100000000.0)" -0.36338508935581
        I'm on Win32, and that's using the Microsoft C runtime library (msvcrt.dll). If I instead use the mpfr library, then I get the correct result:
        C:\_32>perl -MMath::MPFR -e "$x=Math::MPFR->new(100000000.0);print cos +($x)" -3.6338508935569053e-1
        Cheers,
        Rob
Re: cos (100000000.0)
by kennethk (Monsignor) on Sep 01, 2009 at 15:01 UTC
    Did you try checking out the site archives? For example, yesterday someone asked a very similar question with An arithmetic oddity and a Super Search for precision yields a large number of results, and the first one (int($x) gives strange result) is a good discussion of exactly this issue.

    Please read up on how floating point arithmatic works - for example What Every Computer Scientist Should Know About Floating-Point Arithmetic. I suspect that in C++ you are invoking the single precision cosine function (or maybe just the single-precision string format for output) and double precision in Java and Perl - doesn't it strike you as odd that it returns half as many digits? And I would like to know why you think any of those are more or less accurate - have you actually calculated the analytical answer? And what are you trying to do that requires 16 digits of precision - the Planck constant is only known to 8.

    In short, what are you really trying to do? This sounds a lot like an XY Problem to me.

Re: cos (100000000.0)
by biohisham (Priest) on Sep 01, 2009 at 18:43 UTC
    There's something related to Arbitrary-precision Arithmetic, I am not strong in Maths but from this query I got me curious and I found out that perl can allow you to use that sort of precision Arithmetic, please see, Arithmetic.

    I know that negating 0 would give you the unsigned integer capacity of your machine, if this is got to do with addressing your problem, then I hope I have been able to contribute and I'd be happy, otherwise, I'd be happy as well if someone corrected me.

    printf "%e", ~0;

    Excellence is an Endeavor of Persistence. Chance Favors a Prepared Mind.

      I know that negating 0 would give you the unsigned integer capacity of your machine, if this is got to do with addressing your problem,

      Both numbers fit into a double-precision float (the minimum size Perl uses for floats), so it's not a question of machine precision. It's a question of the precision/accuracy of the cos function.

      Note that the Config module provides information on the size of number types used internally.

      $ perl -V:ivsize 4: -2**(4*8-1) .. 2**(4*8-1)-1 ivsize='4'; 8: -2**(8*8-1) .. 2**(8*8-1)-1 $ perl -V:uvsize 4: 0 .. 2**(4*8)-1 uvsize='4'; 8: 0 .. 2**(8*8)-1 $ perl -V:nvsize 8: double, 53 bits of precision nvsize='8'; 16: quad, 113 bits of precision
Re: cos (100000000.0)
by FunkyMonk (Canon) on Sep 01, 2009 at 23:26 UTC
    Given the points about floating point numbers that other Monks have mentioned, there's a few points I'd like to raise:

    • Why are you taking the cosine of 100 million radians? I cannot think of any valid reason for doing that.
    • Why do you care that the answer has an error of 1 part in 1,000,000,000,000?
    • Why do you assume that it's perl that has the wrong answer?
    Finally, my 64-bit perl running on AMD gives:

    $ perl -le 'printf "%.55f\n", cos(100_000_000.0)' -0.3633850893556905270465051671635592356324195861816406250

    Thus proving that Perl >> Java >> C++, AMD >> Intel and that Thursday is the new pink :-)

      Why are you taking the cosine of 100 million radians? I cannot think of any valid reason for doing that.

      Amen to that.

      To the OP: trigonometric functions are about the most unreliable calculations that you can do on a computer. I think it is just not reasonable to expect very precise results, for such a huge parameter value. Actually, the difference in results between the different implementations is a lot smaller, than I had anticipated.

      Floating point in Perl has about 15 significant digits. For a function like cos, the digits before the decimal point don't really matter, as you may just as well use the parameter value modulo 2*PI, and (ideally) expect the same outcome. That means that for this parameter, with 8 digits wasted, you have about 6-7 significant digits left. That is how close you may expect the result of the calculation of cos to be.

      I am guessing you just made that parameter up, as a silly test.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://792659]
Approved by ikegami
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (13)
As of 2014-12-18 09:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (48 votes), past polls