Ultrashock Forums > Flash > ActionScript > UltraMath
• cos and sin not working properly??

You are currently viewing our website as a guest which gives you limited access to forums, files and other resources.

Click here to join now for free, and start interacting with our members, download files and much more!

Click here if you are looking for our Flash files and other professional assets.
 
Post Reply | View first unread | Rate Thread Search this Thread | Thread Tools | Display Modes

#1
Bookmark and Share!
cos and sin not working properly??
Old 2003-08-29

if you take the sin of PI you should get 0.......
ActionScript Code:
  1. trace(Math.sin(Math.PI))

instead it is tracing
1.22460635382238e-16

also geting strage values for Math.cos(Math.PI/2)....90 degrees.....aswell as Math.sin(2*Math.PI)

what have i done wrong
postbit arrow 5 comments | 862 views postbit arrow Reply: with Quote   
Registered User
emothawd is offline
seperator
Posts: 28
2003-07-10
seperator

Ultrashock Member Comments:
andreaskr andreaskr is offline 2003-08-30 #2 Old  
Last edited by andreaskr : 2003-08-30 at 04:19.
Thatīs almost 0. The result isnīt 0 because Pi has no exact value (Pi=3.14.......).

try this..

ActionScript Code:
  1. trace(int(Math.sin(Math.PI)))

...and the result will be 0.
Reply With Quote  
Dickee Dickee is offline 2003-08-30 #3 Old  
Last edited by Dickee : 2003-09-03 at 23:25.
I realize that andreaskr was only using 'int' to create the example, but it should never be used when dealing with cos and sin values, both of which range between -1<0<1 ... for any values other than the extremes of 1 and -1, the result when applying 'int' will be 0.

The problem is actually caused by the 'IEEE floating point error' which is well documented on the net. The examples below show that subtracting 1e-16 has no effect, but 1e-15 does affect the result.

Jon Bradley has formulated an algorithm to deal with epsilon in Flash posted here. I'm not sure why he has used 256 for the 's' fraction and loop counter, rather than 308.25... (close to Flash's MIN_VALUE/MAX_VALUE power as I've used in my experimentation, resulting in different max/min 'close to 0' values) ... no doubt that it has to do with the bitwise operations (256 = 2^8) that are causing the rounding error. Since his formal name has a baccalaureate appendage and mine does not, let's go with Jon's work!

Code:
// ----------------------------------------
// Machine Error : Epsilon
// Find the smallest E such that 1 + E > 1
//
// Author: Jon Bradley
// ----------------------------------------

// ----------------------------------------
// Machine Error : Epsilon
// Find the smallest E such that 1 + E > 1
//
// Author: Jon Bradley
// ----------------------------------------

function getEpsilon()
{

	var s = 1/Math.pow(10, 256);

	for (var i = 0; i<256; i++)
	{
		s *= 10;
		if (1 + s > 1)
		{
			break;
		} else
		{
			epsilon = s;
		}
	}

	Math.EPSILON = epsilon;
	return epsilon;
}
e = getEpsilon();
trace(e);
Examples:

Code:
// 1. Your example for the angle 180°: 
("1. "+trace(Math.sin(Math.PI))) // 1.22460635382238e-16
// 2. when 'int' is applied:
trace("2. "+(int(1.22460635382238e-16))); // 0
// 3. however, when the angle is 90° 
trace("3. "+(Math.sin(.5*Math.PI))) // 1
// 4. when your 180° result is applied to an angle of 90°:
trace("4. "+(Math.sin(.5*Math.PI)-Math.sin(Math.PI))) // 1
// 5. same thing with the actual result plugged in:
trace("5. "+(Math.sin(.5*Math.PI)-1.22460635382238e-16)) // 1
// 6. however, when 1e-15 is subtracted, the reult is different:
trace("6. "+(Math.sin(.5*Math.PI)-1.22460635382238e-15)) // 0.999999999999999
// 7. when 'int' is applied to #6:
trace("7. "+int((Math.sin(.5*Math.PI)-1.22460635382238e-15))) // 0
// 8. which when dealing with cos and sin, are very different results
trace("8. "+(int(-0.999999999999999))); // 0
// 9. and the same happens with the positive case
trace("9. "+int((1-(1e-15)))); // 0
// more examples
trace("10. "+(Math.sin(2*Math.PI))); // -2.44921270764475e-16
trace("11. "+(Math.cos(2*Math.PI))); // 1
trace("12. "+(int(Math.sin(2*Math.PI)))); // 0
trace("13. "+(Math.cos(2*Math.PI)-Math.sin(2*Math.PI))); // 1
trace("14. "+(int(Math.cos(2*Math.PI)-Math.sin(2*Math.PI)))); // 1
trace("15. "+(Math.cos(2*Math.PI)-Math.sin(2*Math.PI)-.1)); // 0.9
trace("16. "+(int(Math.cos(2*Math.PI)-Math.sin(2*Math.PI)-.1))); // 0
trace("17. "+(int(Math.cos(2*Math.PI)-Math.sin(2*Math.PI)-1e-15))); // 0
trace("18. "+(int(Math.cos(2*Math.PI)-Math.sin(2*Math.PI)-1e-16))); // 1
// all around the circle
trace("19. "+(Math.sin(.5*Math.PI))); // 6.12303176911189e-17
trace("20. "+(Math.cos(.5*Math.PI))); // 1.22460635382238e-16
trace("21. "+(Math.sin(Math.PI))); // -2.44921270764475e-16
trace("22. "+(Math.cos(Math.PI))); // -1
trace("23. "+(Math.sin(1.5*Math.PI))); // -1
trace("24. "+(Math.cos(1.5*Math.PI))); // -1.83690953073357e-16
trace("25. "+(Math.sin(2*Math.PI))); // -2.44921270764475e-16
trace("26. "+(Math.cos(2*Math.PI))); // 1
// one more showing 'int' misuse
trace("27. "+(Math.sin(1.5*Math.PI)+.1)); // -.9
trace("28. "+(int(Math.sin(1.5*Math.PI)+.1))); // 0
Richard
Reply With Quote  
emothawd emothawd is offline 2003-08-30 #4 Old  
great info thanks alot...you learn more everyday
Reply With Quote  
Dickee Dickee is offline 2003-09-03 #5 Old  
Last edited by Dickee : 2003-09-04 at 08:48.
Hey Matrix!

That's probably the worst reason to go with anything.
So, you feel that my hoed-road, the 'School of Hard Knocks', is the preferred path to follow, rather than the hallowed halls of post-secondary masochism? I'll keep that in mind!

<edit>
If you're having trouble following this ... Matrix posted twice with some valuable information and links to info on the LAPACK algorithm, but for some reason his posts were deleted from the thread. ???!

I couldn't follow the Fortran script, I'm afraid, so I googled a JavaScript example from:

http://www3.telus.net/thothworks/MachEps.html

.. which when tested in the Flash environment, returned the same results as the page's display, differing from the results of Jon's 'getEpsilon()' function, which returns 9.99999999999999e-17 on my Athlon XP-2200 (Windows):

Code:
dbleEpsilon = function() {
    var temp1,temp2,mchEps;
    temp1 = 1.0;
    do {
        mchEps = temp1;
        temp1 /= 2;
        temp2 = 1.0+temp1;
    } while (temp2>1.0);
    return mchEps;
};

trace (dbleEpsilon()); // 2.22044604925031e-16
Would this be more in line with the LAPACK algorithm results?

BTW, I emailed Jon to get his view of the situation, but so far, no reply.

Richard
Reply With Quote  
jbradley jbradley is offline 2003-09-04 #6 Old  
The IEEE floating point arithmatic library defines a certain specified way of calculating floating point operations. The Double Precision (64 bit) Machine Epsilon is defined as 2^-53 or approximately 1.11 x 10^-16.

Your results of double-epsilon return approximately twice that value, whice is accurate.

This epsilon algorithm used may underestimate the true error by a factor p(n) <= 10n. This means that although you get the same results in both places, there's no real way to know whether or not your calculation is accurate with that algorithm within a boundary of approximately 1x10-16.

Good job hunting that equation down. It results in the direct calculation of the machine error - very good.

Even then, there's a very good chance that running mathematical operations under the limit I provided, but above the limit this algorithm generates will not be stable.

best,

Jon B.
Reply With Quote  
Thread Tools
Display Modes Rate This Thread
Rate This Thread: