From: Robert Klemme Date: 2009-12-23T21:56:40+09:00 Subject: Re: Trig value errors 2009/12/23 jzakiya : > On Dec 23, 12:42 am, Phrogz wrote: >> On Dec 22, 10:07 pm, Phrogz wrote: >> >> > irb(main):004:0> x = cos(onedegree/1e06) >> > => 1.0 >> > irb(main):005:0> x - 1.0 >> > => -1.11022302462516e-16 >> > irb(main):006:0> puts "%.30f" % x >> > 0.999999999999999888977697537484 >> >> As an interesting and related aside, I wanted to find out what the >> correct value for this calculation was (to a certain number of >> decimals). I thought asking Alpha would be an easy place to start. >> >> This query (which has the parameter off by a factor of 1000) works:http://www.wolframalpha.com/input/?i=cos%28+2*pi+%2F+360+%2F+1e3+%29 >> and results in: >> 0.9999999998476912901 >> >> Trying for smaller parameter values, however, results in Alpha giving >> up:http://www.wolframalpha.com/input/?i=cos%28+2*pi+%2F+360+%2F+1e4+%29 >> (For me, that query always results in a message: "This Wolfram|Alpha >> server is temporarily unavailable.") > > You are correct, arithmetically: > > 2*PI/360 => 0.0174532925199433 # equiv to 1.0 degree > > I incorrectly wrote in the post the value for: > 2*PI/260 => 0.0241660973353061 # equiv to 1.38 degree > > This didn't nullify THE POINT I illustrated, which was > using an increasingly smaller angle approaching zero as > an argument, it eventually produced a value of '1' for > cos, but not '0' for the same sin angle, as it should. > > I feel I've made my points as clear as I think is needed. > If it doesn't bother you that the present implementation produces > incorrect results for clearly unambiguous > situations then we just have different standards for the > need to adhere to mathematical rigor and produce exact > results. BUT THAT IS A CHOICE THAT HUMANS MAKE, AND IS > NOT MANDATED BY NATURE. Please don't shout. Not sure what the term "nature" means here. AFAIK mathematics are a human invention... > Again, one really simple fix to eliminate these ERRORS > is to do something like the following in the Math module. > > rename current functions as follows: > cos > cosine; sin > sine, tan > tangent > > then redefine old aliases so that: > > def cos(x); cosine(x).abs < 1e-11 ? 0.0 : cosine(x) end > def sin(x); sine(x).abs < 1e-11 ? 0.0 : sin(x) end > def tan(x); sin(x)/cos(x) end > > If you want define: TRIG-EPSILON = 1e-11, or whatever, > so you can change it easily and make it available. > > With these simple changes you even get the added benefit > that tan(PI/2) => Infinity as it should (1/0), instead of > currently tan(PI/2) => 1.63317787283838e16 This would be a bad idea. As John stated already, values returned from these functions are mandated by IEEE 754 standard. Changing how these fundamental functions behave is calling for trouble. The very moment you do that, completely unrelated code may break. If you insist on getting the results you are expecting there's nothing stopping you from defining your own versions under a different name and use those in your calculations. Otherwise you should use a system for symbolic math as Jean-Julien suggested. Btw, your own example proves that we are talking about an _arithmetic_ error and not a _mathematical_ error. A mathematical error in my eyes would be if Math.sin(Math::PI / 2) returned something negative. Kind regards robert Further reading: http://en.wikipedia.org/wiki/IEEE_754 You can also search the archives for "rounding error" or "bug float" and will find more than enough material. -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/