From: Robert Klemme Date: 2009-12-27T02:45:07+09:00 Subject: Re: Trig value errors On 26.12.2009 15:43, Rick DeNatale wrote: > On Sat, Dec 26, 2009 at 4:56 AM, Brian Candler wrote: > >> Floating-point can represent smaller increments the closer you get to >> zero. So values of 0 +/- dX can be represented much more accurately than >> 1 +/- dX. > > Strictly speaking they can be represented much more precisely. Are you sure you meant "precisely" and not "accurately"? Given the Wikipedia article you quote it seems _that_ is what you rather wanted to say. > Precision and accuracy are different things. > > http://en.wikipedia.org/wiki/Accuracy_and_precision In light of the article the term "precision" (aka "repeatability") is pretty meaningless in this case (you could also say "uninteresting") because due to the deterministic nature of the implementation of trigonometric functions the result is always identical for the same input. It is the accuracy that the whole thread revolves around. IEEE standards mandate a certain accuracy and people who need better accuracy need to use specialized tools - either math libraries with higher accuracy (or even selectable accuracy) or tools that do symbolic math. Also, as elsewhere in this thread has been explained, the "correction" approach suggested (if the abs is lower than a particular epsilon, return 0 instead of the value) is a pretty bad one - much worse than general rounding of values because it introduces distorted accuracy. Rounding is better because it generally cuts off digits; which is ironic because it *reduces* overall accuracy of the function... Kind regards robert A program that nicely demonstrates the nonlinearity of the error introduced by the suggested "fix": module Math def sin2(x, epsilon = 1e-10) y = sin(x) y.abs < epsilon ? 0.0 : y end end include Math # find interesting start value div = 1.2 x = 1.0 x /= div while sin(x) == sin2(x) x *= div ** 10 # do the test 100.times do |i| y1 = sin(x) y2 = sin2(x) printf "%6d %20e %20e %20e error: %20e\n", i, x, y1, y2, ((y2-y1)/x).abs x /= div end -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/