Trig value errors

B

Brian Candler

If the objective is for sin() to be equally inaccurate/imprecise around
0.0 as it is around 1.0, then try this:

module Math
def sin2(x)
1.0 - (1.0 - sin(x))
end
module_function :sin2
end
 
J

jzakiya

If the objective is for sin() to be equally inaccurate/imprecise around
0.0 as it is around 1.0, then try this:

module Math
  def sin2(x)
    1.0 - (1.0 - sin(x))
  end
  module_function :sin2
end


=> 0.0174532925199433>> sin(od/1e8)

=> 1.74532925199433e-10>> sin2(od/1e8)

=> 1.74532943653105e-10>> sin(od/1e16)

=> 1.74532925199433e-18>> sin2(od/1e16)
=> 0.0

Here's the nature of the problem.

Ruby currently gives incorrect values for x|y axis angles
cos PI/2 => 6.12303176911189e-17
sin PI => 1.22460635382238e-16
cos 3*PI/2 => -1.83690953073357e-16
sin 2*PI => -2.44921970764475e-16

Thus, sin gives incorrect answers on the +|- x axis
and, cos gives incorrect answers on the +|- y axis

Here's the total solution.

In order to produce the mathematically correct answers
we must FORCE the answers to meet mathematical necessity.

i.e. (1) 1 = cos^2 + sin^2

thus, (2) cos|sin = [1-(sin|cos)^2]^(1/2)

also, (3) for angle x when sin|cos= -1|1 > cos|sin= 0.0

To 'fix totally' these errors in sin|cos near the x|y axis define sin1|
cos1 here using Ruby's native cos|sin.

def sin1(x)
y=(1-cos(x)**2)**0.5 # calculate (2)
return 0.0 if y==0
return sin(x) < 0 ? -y : y # for correct quadrant sign
end

def cos1(x)
y=(1-sin(x)**2)**0.5 # calculate (2)
return 0.0 if y==0
return cos(x) < 0 ? -y : y # for correct quadrant sign
end


Now sin|cos == sin1|cos1 for all angles -1|1 degree from
each axis.

For |x| < 1 degree from 0, 90, 180, 270, 360, and their
multiples, sin1|cos1 will produce the mathematically
correct complimentary answers to satisfy (1) and (3).

In testing, I found only one instance on each side of
each +|- axis where the floating point approximations
gave answers which violated (3).

Here's an example at 0 degrees|radians

first let:
degrees = PI/180

x|y axis check
sin1(0*degrees) => 0.0
cos1(0*degrees) => 1.0
sin1(90*degrees) => 1.0
cos1(90*degrees) => 0.0
sin1(180*degrees) => 0.0
cos1(180*degrees) => -1.0
sin1(270*degrees) => -1.0
cos1(270*degrees) => 0.0
sin1(360*degrees) => 0.0
cos1(360*degrees) => 1.0

1st Quadrant
sin1((0+1e-5)*degrees) => 1.74413620095247e-07
cos1((0+1e-5)*degrees) => 0.999999999999985
sin1((0+1e-6)*degrees) => 1.49011611938477e-08
cos1((0+1e-6)*degrees) => 1.0 # this pair violates (3)
sin1((0+1e-7)*degrees) => 0.0 # correct now for
cos1((0+1e-7)*degrees) => 1.0 # both as angle gets
sin1((0+1e-8)*degrees) => 0.0 # closer and closer
cos1((0+1e-8)*degrees) => 1.0 # to x-axis

4th Quandrant
sin1((0-1e-5)*degrees) => -1.74413620095247e-07
cos1((0-1e-5)*degrees) => 0.999999999999985
sin1((0-1e-6)*degrees) => -1.49011611938477e-08
cos1((0-1e-6)*degrees) => 1.0 # this pair violates (3)
sin1((0-1e-7)*degrees) => 0.0 # correct now for
cos1((0-1e-7)*degrees) => 1.0 # both as angle gets
sin1((0-1e-8)*degrees) => 0.0 # closer and closer
cos1((0-1e-8)*degrees) => 1.0 # to x-axis

Also for 4th Quadrant
sin1((360-1e-5)*degrees)=> -1.74413620095247e-07
cos1((360-1e-5)*degrees)=> 0.999999999999985
sin1((360-1e-6)*degrees)=> -1.49011611938477e-08
cos1((360-1e-6)*degrees)=> 1.0 # this pair violates (3)
sin1((360-1e-7)*degrees)=> 0.0 # correct now for
cos1((360-1e-7)*degrees)=> 1.0 # both as angle gets
sin1((360-1e-8)*degrees)=> 0.0 # closer and closer
cos1((360-1e-8)*degrees)=> 1.0 # to x-axis

This shows that the precision, or the smallest unit value
of an angle you can resolve, is on the order of |1e-5| at x|y-axis.
Any thing smaller provides no precision toward the answer, no matter
how many decimal places past this point you choose to calculate. These
are the most non-linear regions in the series expansion for cos|sin.

The same effect occurs as you increase the angle size,
but you can get greater precision (angle resolution),
with the greatest resolution occurring at |45| degrees.
Here, you get about |1e-14| degrees of angular precsion.
ie, as you go from 45-1e-14 > 45-1e-15 cos|sin stay the
same for smaller and smaller delta angles.

Now, sin1|cos1 (and tan1=sin1/cos1) meet the mathematical
requirements of (1),(2),(3) and are as inherently precise
as the underlying trig lib, and can become more precise as the trig
lib functions get better and/or the cpu size grows

They can NEVER BE WORSE than the native trig lib functions, and will
ALWAYS be mathematically MORE accurate, because they are DESIGNED to
meet mathematical trig requirements.

I would PROPOSE that Ruby adopt the structure presented
here and implement them in the C source to make them as
fast and efficient to compute as possible.

I would ENCOURAGE people to actually run|test the code
against the present trig functions to see for themselves
that they work for ALL angles.

This was done with Ruby 1.9.1p243 on Intel P4 cpu system.
 
J

John W Higgins

[Note: parts of this message were removed to make it a legal post.]

i.e. (1) 1 = cos^2 + sin^2

This also means that 0 = 1 - cos^2 - sin^2

To 'fix totally' these errors in sin|cos near the x|y axis define sin1|
cos1 here using Ruby's native cos|sin.

def sin1(x)
y=(1-cos(x)**2)**0.5 # calculate (2)
return 0.0 if y==0
return sin(x) < 0 ? -y : y # for correct quadrant sign
end

def cos1(x)
y=(1-sin(x)**2)**0.5 # calculate (2)
return 0.0 if y==0
return cos(x) < 0 ? -y : y # for correct quadrant sign
end
You are simply unable to apparently grasp how mathematics works with
floating point numbers. So lets make a very simple example which shows that
your method fails as badly as does the standard methods.

First, to show that the standard methods show no greater precision lets test
87 degrees shall we.

1.0 - (sin(PI/180*87) ** 2 + cos(PI/180*87) ** 2)
=> 1.11022302462516e-16

So we fail with the standard and yours works

1.0 - (sin1(PI/2/90*87) ** 2 + cos1(PI/2/90*87) ** 2)
=> 0.0

But wait shall we - lets look at 67 degrees ok?

1.0 - (sin(PI/180*67) ** 2 + cos(PI/180*67) ** 2)
=> 0.0

1.0 - (sin1(PI/180*67) ** 2 + cos1(PI/180*67) ** 2)
=> 2.22044604925031e-16

Oh no - we have a problem - your calculation fails when the standard works.

There is no way to accurate get these values to ever work with floating
point mathematics. There will always be something that fails because all you
are doing is trying to cover up one inaccurate calculation with yet another
inaccurate calculation.

If you hide yourself in a box that is only 1 or 0 shockingly you can make
x^2 + y^2 = 1 because you are gaming the values. But you fail to appreciate
that the numbers will always have an element of imprecision that you have no
control over and you cannot make work to exact numbers when dealing with
floating points.

Yet again, the standard is the standard because a lot of VERY smart people
took the time to analyze the entire spectrum of results instead of limiting
themselves myopically to one particular area.

John
 
J

jzakiya

[Note:  parts of this message were removed to make it a legal post.]

i.e.  (1) 1 = cos^2 + sin^2

This also means that 0 = 1 - cos^2 - sin^2




To 'fix totally' these errors in sin|cos near the x|y axis define sin1|
cos1 here using Ruby's native cos|sin.
def sin1(x)
 y=(1-cos(x)**2)**0.5        # calculate (2)
 return 0.0 if y==0
 return sin(x) < 0 ? -y : y  # for correct quadrant sign
end
def cos1(x)
 y=(1-sin(x)**2)**0.5        # calculate (2)
 return 0.0 if y==0
 return cos(x) < 0 ? -y : y  # for correct quadrant sign
end

You are simply unable to apparently grasp how mathematics works with
floating point numbers. So lets make a very simple example which shows that
your method fails as badly as does the standard methods.

First, to show that the standard methods show no greater precision lets test
87 degrees shall we.

1.0 - (sin(PI/180*87) ** 2 + cos(PI/180*87) ** 2)
=> 1.11022302462516e-16

So we fail with the standard and yours works

1.0 - (sin1(PI/2/90*87) ** 2 + cos1(PI/2/90*87) ** 2)
=> 0.0

But wait shall we - lets look at 67 degrees ok?

1.0 - (sin(PI/180*67) ** 2 + cos(PI/180*67) ** 2)
=> 0.0

1.0 - (sin1(PI/180*67) ** 2 + cos1(PI/180*67) ** 2)
=> 2.22044604925031e-16

Oh no - we have a problem - your calculation fails when the standard works.

There is no way to accurate get these values to ever work with floating
point mathematics. There will always be something that fails because all you
are doing is trying to cover up one inaccurate calculation with yet another
inaccurate calculation.

If you hide yourself in a box that is only 1 or 0 shockingly you can make
x^2 + y^2 = 1 because you are gaming the values. But you fail to appreciate
that the numbers will always have an element of imprecision that you haveno
control over and you cannot make work to exact numbers when dealing with
floating points.

Yet again, the standard is the standard because a lot of VERY smart people
took the time to analyze the entire spectrum of results instead of limiting
themselves myopically to one particular area.

John

All I can say is....

Against stupidity the Gods themselves contend in vain. :(
 
S

Seebs

All I can say is....

Against stupidity the Gods themselves contend in vain. :(

This adequately summarizes the difficulty people have had getting you to
understand why it is ridiculous to try to "fix" sin(180) but not to try to
"fix" sin(45).

-s
 
J

jzakiya

This adequately summarizes the difficulty people have had getting you to
understand why it is ridiculous to try to "fix" sin(180) but not to try to
"fix" sin(45).

-s

No, YOU still don't seem to know the difference between
precision an accuracy.

If you can READ I said my method is no more precise, i.e
it CANNOT resolve angular differences past the inherent
precision of the native trig functions.

But what you, and your cohorts, don't want to deal with, is my method
IS MORE ACCURATE for sin|cos on the x|y axis angles, whereas the
native functions are INACCURATE.

So, I DON'T CARE how precise any of the other angles
are, because they all are ACCURATE to the precision that
the native functions have. I said this many times, and
others have tried to explain the difference too.

One thing is VERY CLEAR though.

YOU, can't SHOW that my method is inaccurate for any
angle value. Can YOU?

Ah... A Brain is such a terrible thing to waste. :(
 
W

Walton Hoops

No, YOU still don't seem to know the difference between
precision an accuracy.

If you can READ I said my method is no more precise, i.e
it CANNOT resolve angular differences past the inherent
precision of the native trig functions.

But what you, and your cohorts, don't want to deal with, is my method
IS MORE ACCURATE for sin|cos on the x|y axis angles, whereas the
native functions are INACCURATE.

So, I DON'T CARE how precise any of the other angles
are, because they all are ACCURATE to the precision that
the native functions have. I said this many times, and
others have tried to explain the difference too.

One thing is VERY CLEAR though.

YOU, can't SHOW that my method is inaccurate for any
angle value. Can YOU?
Actually, he did... lets review:


First, to show that the standard methods show no greater precision lets test
87 degrees shall we.

1.0 - (sin(PI/180*87) ** 2 + cos(PI/180*87) ** 2)
=> 1.11022302462516e-16

So we fail with the standard and yours works

1.0 - (sin1(PI/2/90*87) ** 2 + cos1(PI/2/90*87) ** 2)
=> 0.0

But wait shall we - lets look at 67 degrees ok?

1.0 - (sin(PI/180*67) ** 2 + cos(PI/180*67) ** 2)
=> 0.0

1.0 - (sin1(PI/180*67) ** 2 + cos1(PI/180*67) ** 2)
=> 2.22044604925031e-16

Oh no - we have a problem - your calculation fails when the standard works.


Thus, your method is inaccurate for the angle value of 67.
 
J

jzakiya

Actually, he did... lets review:










Thus, your method is inaccurate for the angle value of 67.

My methods
sin1(67*degrees) => 0.92050485345244
cos1(67*degrees) => 0.39073112848927

Ruby methods
sin(67*degrees) => 0.92050485345244
cos(67*degrees) => 0.39073112848927

Same answers.

It's clear you jokers just like to argue and spew nonsense. You make
stupid statements and provide no
data to establish your claims. But I guess well thought
out and consistent reproducible claims are just too
much for you guys to produce.

Are you guys Republicans and/or Global Climate Change deniers too?
 
J

John W Higgins

[Note: parts of this message were removed to make it a legal post.]

One thing is VERY CLEAR though.

YOU, can't SHOW that my method is inaccurate for any
angle value. Can YOU?

This is getting funnier by the moment. Gotta love someone that just doesn't
grasp utter failure. So we've got 67 degrees on the high side and how about
we pull out nice low number now to completly end the conversation. Lets try
4.269e-07 degrees shall we?

z = 4.269e-07

1.0 - (sin(PI/180*z) ** 2 + cos(PI/180*z) ** 2)
=> 0.0

Standard functions pass - anyone wanna guess what we're going to find when
we try the new concept? Anyone? Bueller?

1.0 - (sin1(PI/180*z) ** 2 + cos1(PI/180*z) ** 2)
=> 2.22044604925031e-16

Have you had enough?

John
 
J

John W Higgins

[Note: parts of this message were removed to make it a legal post.]

My methods
You just will never ever get it will you?

cos1(67*degrees) - 0.39

0.000731128489273647

cos(67*degrees) - 0.39

0.000731128489273702

Got a problem don't we? Displayed value DOES NOT equal actual value. The
system displays x digits on the screen but stores y.

John
 
W

Walton Hoops

My methods

Ruby methods


Same answers.
Really? huh....

irb(main):017:0> def sin1(x)
irb(main):018:1> y=(1-cos(x)**2)**0.5 # calculate (2)
irb(main):019:1> return 0.0 if y==0
irb(main):020:1> return sin(x) < 0 ? -y : y # for correct quadrant sign
irb(main):021:1> end
=> nil
irb(main):022:0> def cos1(x)
irb(main):023:1> y=(1-sin(x)**2)**0.5 # calculate (2)
irb(main):024:1> return 0.0 if y==0
irb(main):025:1> return cos(x) < 0 ? -y : y # for correct quadrant sign
irb(main):026:1> end
=> nil
irb(main):027:0> degrees=PI/180
=> 0.0174532925199433
irb(main):028:0> s0=sin1(67*degrees)
=> 0.92050485345244
irb(main):029:0> c0=cos1(67*degrees)
=> 0.390731128489274
irb(main):030:0> s1=sin(67*degrees)
=> 0.92050485345244
irb(main):031:0> c1=cos(67*degrees)
=> 0.390731128489274
irb(main):032:0> s0==s1
=> false
irb(main):033:0> c0==c1
=> false
irb(main):034:0> s0-s1
=> -1.11022302462516e-16
irb(main):035:0> c0-c1
=> -5.55111512312578e-17
irb(main):036:0>


whoops.. guess they aren't equal after all.

Similarly, from one of your earlier examples:

irb(main):036:0> s=sin((360-1e-6)*degrees)
=> -1.74532923897938e-08
irb(main):037:0> c=cos((360-1e-6)*degrees)
=> 1.0
irb(main):038:0> c==1
=> false
irb(main):039:0> 1-c
=> 1.11022302462516e-16

That 1 isn't really a 1. This has been pointed out before, you just
chose to ignore it.
 
S

Seebs

No, YOU still don't seem to know the difference between
precision an accuracy.

I certainly do.
If you can READ I said my method is no more precise, i.e
it CANNOT resolve angular differences past the inherent
precision of the native trig functions.
Right.

But what you, and your cohorts, don't want to deal with, is my method
IS MORE ACCURATE for sin|cos on the x|y axis angles, whereas the
native functions are INACCURATE.

For any point you special case, there is a range of possible inputs
which yield something close enough that you automatically round it.
For all but one of those inputs, your method is LESS ACCURATE.

There is no reason to treat those particular points as specially
deserving of extra accuracy, to such an extent that you should
make other nearby input values less accurate.
YOU, can't SHOW that my method is inaccurate for any
angle value. Can YOU?

We already went through this. Your method is inaccurate for any
value for which the resulting value is within the range you picked
of values which are "really close to zero". In the long run, there
are many, many, more such values than there are values for which your
method is "more accurate".

Again, the problem here is simply that you don't understand what
rounding is, and when it should be done. If you want round numbers,
round them. Don't add a large computational expense (keep in mind
that on some machines, sin(x) may be in hardware, so you're replacing
a single instruction with a large hunk of interpreted code) to every
single trig function, introducing errors for a large number of them,
just to avoid having to round values if you want them rounded.

Let's see. You originally set your boundary to 1e-11, then improved
it to 1e-14, yes? Okay, let's see. Here's a range of values
(in doubles, since you were complaining about an e-16) near 180 which
produce values ranging from 1e-14 to -1e-14. You will notice
that, for all of these values except the one right in the middle,
yours produces an inaccuracy GREATER in magnitude than the
inaccuracy reported for 180.0. Which is to say... It's wrong
more often than it's right, and by a larger margin.

sin(179.99999999999940314410) = 1.0336512461933677897718553e-14
sin(179.99999999999943156581) = 9.8924232520836152815491005e-15
sin(179.99999999999945998752) = 9.4483340422335526653796478e-15
sin(179.99999999999948840923) = 9.0042448323834900492101951e-15
sin(179.99999999999951683094) = 8.5601556225334274330407425e-15
sin(179.99999999999954525265) = 8.1160664126833648168712898e-15
sin(179.99999999999957367436) = 7.6719772028333022007018371e-15
sin(179.99999999999960209607) = 7.2278879929832395845323845e-15
sin(179.99999999999963051778) = 6.7837987831331769683629318e-15
sin(179.99999999999965893949) = 5.8956203634330517360240265e-15
sin(179.99999999999968736120) = 5.4515311535829891198545738e-15
sin(179.99999999999971578291) = 5.0074419437329265036851211e-15
sin(179.99999999999974420462) = 4.5633527338828638875156685e-15
sin(179.99999999999977262632) = 4.1192635240328012713462158e-15
sin(179.99999999999980104803) = 3.6751743141827386551767631e-15
sin(179.99999999999982946974) = 3.2310851043326760390073105e-15
sin(179.99999999999985789145) = 2.7869958944826134228378578e-15
sin(179.99999999999988631316) = 1.8988174747824881904989525e-15
sin(179.99999999999991473487) = 1.4547282649324255743294998e-15
sin(179.99999999999994315658) = 1.0106390550823629581600471e-15
sin(179.99999999999997157829) = 5.6654984523230034199059446e-16
sin(180.00000000000000000000) = 1.2246063538223772582114179e-16
sin(180.00000000000002842171) = -3.2162857446782489034831087e-16
sin(180.00000000000005684342) = -7.6571778431788750651776354e-16
sin(180.00000000000008526513) = -1.2098069941679501226872162e-15
sin(180.00000000000011368684) = -1.6538962040180127388566689e-15
sin(180.00000000000014210855) = -2.5420746237181379711955742e-15
sin(180.00000000000017053026) = -2.9861638335682005873650269e-15
sin(180.00000000000019895197) = -3.4302530434182632035344795e-15
sin(180.00000000000022737368) = -3.8743422532683258197039322e-15
sin(180.00000000000025579538) = -4.3184314631183884358733849e-15
sin(180.00000000000028421709) = -4.7625206729684510520428375e-15
sin(180.00000000000031263880) = -5.2066098828185136682122902e-15
sin(180.00000000000034106051) = -5.6506990926685762843817429e-15
sin(180.00000000000036948222) = -6.5388775123687015167206482e-15
sin(180.00000000000039790393) = -6.9829667222187641328901009e-15
sin(180.00000000000042632564) = -7.4270559320688267490595535e-15
sin(180.00000000000045474735) = -7.8711451419188893652290062e-15
sin(180.00000000000048316906) = -8.3152343517689519813984589e-15
sin(180.00000000000051159077) = -8.7593235616190145975679116e-15
sin(180.00000000000054001248) = -9.2034127714690772137373642e-15
sin(180.00000000000056843419) = -9.6475019813191398299068169e-15
sin(180.00000000000059685590) = -1.0091591191169202446076270e-14

-s
 
P

pharrington

My methods


Ruby methods


Same answers.

It's clear you jokers just like to argue and spew nonsense. You make
stupid statements and provide no
data to establish your claims. But I guess well thought
out and consistent reproducible claims are just too
much for you guys to produce.
Not sure at this point if you're just a brilliant troll, or actually
believe what you're posting, but I can't sleep right now so :\

But eh,

ruby-1.9.1-p376 > degrees = PI/180
=> 0.0174532925199433
ruby-1.9.1-p376 > sin(67*degrees)
=> 0.92050485345244
ruby-1.9.1-p376 > sin1(67*degrees)
=> 0.92050485345244
ruby-1.9.1-p376 > cos(67*degrees)
=> 0.390731128489274
ruby-1.9.1-p376 > cos1(67*degrees)
=> 0.390731128489274
ruby-1.9.1-p376 > cos(67*degrees) == cos1(67*degrees)
=> false
ruby-1.9.1-p376 > sin(67*degrees) == sin1(67*degrees)
=> false


Are you saying that Ruby is lying about Math.sin and your sin1
functions returning different values? Also, as has been pointed out
previously, what's displayed when a float is converted to a string is
not necessarily indicative of its actual, internal value.

Also, as has been pointed out, Math::pI is *not* the ratio of a
circle's circumference to its diameter, so even disregarding inherent
floating point imprecision, ranting about the miniscule inaccuracy of
trigonomic functions using this value is pointless because *we're not
even using 100% accurate data to begin with*.



Are you guys Republicans and/or Global Climate Change deniers too?
If you're not a troll, you should really calm down, lay off the
mailing lists for awhile, and learn how to rationally think things
through and except advice/criticism
 
R

Ryan Davis

Not sure at this point if you're just a brilliant troll, or actually
believe what you're posting, but I can't sleep right now so :\

DING DING DING DING DING DING DING WE HAVE A WINNER!

Guys, stop feeding.=20

Don't make me bring Ilias back to make you all realize how good we =
currently have it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top