Cos Weirdness

Monkey Forums/Monkey Programming/Cos Weirdness

[VOLOFORCE](Posted March) [#1]
Hi,

there is something weird going on. As far as I can tell from my pathetic math skills, the cos of Angle 90 should be zero. Weirdly when I try this:

Print "WHAT IS COS 90: " + Cos(90) + "WHAT IS SIN 90:" + Sin(90)

creates this output:

WHAT IS COS 90: 1.2167964413833943e-008WHAT IS SIN 90:1.0

I don't really get it...


Gerry Quinn(Posted March) [#2]
It's due to rounding errors. Your float values must be real floats... what target are you using? On the HTML5 target I get 6.123233995736766e-17, which at least is double-precision.

Okay, you are using desktop. You can use double precision values on this by setting the preprocessor value:
#CPP_DOUBLE_PRECISION_FLOATS=True

But see below for an issue.

THe real problem is that floating point numbers are not exact real values, so they do not always give the precise value you expect. If your maths will crash if Cos( Pi/2 ) is not exactly zero, you must set it as a constant. For the same reason, it's generally best to use integers in For.. Next loops. You'll have the same problem in all languages except maybe some functional languages designed for mathematical calculations.

I originally thought it might work better using Cosr and giving Pi/2 in radians, but on my system that made no difference.

EDIT: my guess turned out right when I set the preprocessor value above... Cosr gave double precision result but Cos didn't. I'll report this as a bug - it looks like Monkey doesn't convert these functions properly. Use the standard radian versions
of trig functions if you want double precision - and don't touch the built-in constants such as PI - they are rounded to float values.


[VOLOFORCE](Posted March) [#3]
Interesting... thanks. But I wonder - why am I the first to notice?


Xaron(Posted March) [#4]
Well... many have noticed this. This is a common "problem" since the introduction of floating point numbers (not limited to Monkey). That's why you NEVER ever would compare for equal with a floating point number. Something like If( a = 0.0 ) is a NO NO. ;)

In the world out there usually some thing like an epsilon is defined so you always compare against that, e.g.:

Local eps:Float = 0.00001

If( Abs( a ) < eps )
  'a is zero! Well... Almost
End If



Gerry Quinn(Posted March) [#5]
As for the degree-based trig functions not honouring the preprocessor command, I suspect that most of those who would have noticed would have been using the radian-based trig functions anyway, if they were doing the sort of math where it mattered.

But regardless of precision, you have to deal with the rounding errors. Double precision stores more digits of each floating-point number, so the errors are smaller. But they will always be there.