435,144 Members | 872 Online + Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,144 IT Pros & Developers. It's quick & easy.

math module broken?

 P: n/a Hi all I was helping my niece with her trigonometry homework last night. Her calculator's batteries were flat, so I thought I would use Python's math module to calculate sin, cos, and tan. I tried the example in the text book first, to ensure that I was getting the correct result, but it did not agree. Then my wife had the idea of using the Microsoft calculator in scientific mode, and that one did give the correct result. Here are some examples - sin(32) - Python 0.55142668 Microsoft 0.52991926 cos(32) - Python 0.83422336 Microsoft 0.84804809 tan(32) - Python 0.66100604 Microsoft 0.62486935 Version is Python 2.3.3. I get the same results on Linux and on Windows 2000. I also get the same results using the cmath module. Can someone please explain these discrepancies? Thanks Frank Millman Jul 18 '05 #1
16 Replies

 P: n/a fr***@chagford.com (Frank Millman) writes: sin(32) - Python 0.55142668 Microsoft 0.52991926 Python's number is the sin of 32 radians which is the same as the sin of 0.584 radians. Microsoft's is the sin of 32 degrees which is 0.558 radians, so the results are coincidentally fairly close to one another. Math libraries usually take args in radians while calculators usually let you select between radians and degrees. cos(32) - Python 0.83422336 Microsoft 0.84804809 tan(32) - Python 0.66100604 Microsoft 0.62486935 Same thing. Jul 18 '05 #2

 P: n/a Frank Millman wrote: Hi all I was helping my niece with her trigonometry homework last night. Her calculator's batteries were flat, so I thought I would use Python's math module to calculate sin, cos, and tan. I tried the example in the text book first, to ensure that I was getting the correct result, but it did not agree. Then my wife had the idea of using the Microsoft calculator in scientific mode, and that one did give the correct result. Here are some examples - sin(32) - Python 0.55142668 Microsoft 0.52991926 Version is Python 2.3.3. I get the same results on Linux and on Windows 2000. I also get the same results using the cmath module. Can someone please explain these discrepancies? Both are "correct" if you know what you have been asking for. In standard mathematics the argument to a trigonometric function like sin, cos, tan, ... is in radians (!) This is even the case with most pocket calculators but there you can switch modes. In the example above, Microsoft - something special as ever - seems to expect the argument in degrees (which is quite unusual) Since an argument in radians normally is between 0 and 2*pi or between -pi and pi, an argument of 32 is unusual for a radians argument though perfectly legal. If your input is in degrees, define def mysin(x) return math.sin(x/pi*180) # 1 degree = 180/pi radians (don's use x/180*pi) now print mysin(32) gives 0.529919264233 -- Helmut Jarausch Lehrstuhl fuer Numerische Mathematik RWTH - Aachen University D 52056 Aachen, Germany Jul 18 '05 #3

 P: n/a [Christopher T King] ... Reduction... from 1.0e18?! Of course that doesn't work with radians, it doesn't even works with degrees! Actually, it can. If you view a floating-point number as being exactly what it says it is, then of course there's an exact reduction of that number modulo pi. Very high-quality math libraries compute that too. I know because I wrote one . The popular fdlibm (from Netlib) does "as-if infinite precision" trig argument reduction too. The details can be excruciating. You (of course) need to know pi to greater than machine precision, but not to as much greater as you may think: across all possible 754 doubles, you can find the one closest to being an exact multiple of pi, and you only need to use enough extra precision to get the right answer (to machine precision) in that worst case. At least 3 groups have discovered that independently (I was one of them, discovered when writing a libm for Kendall Square Research in the early 90's, in collaboration with Peter Tang). IIRC, Mary Payne at DEC was the first to implement "infinite precision" trig argument reduction in a commercial math library, and she wrote a very readable paper about it I'm unable to find now. She wasn't able to put an a priori bound on the amount of precision needed, so it was less efficient than later attempts. All in all, and despite having pushed the state of the art there myself, it's a silly thng to bother with . Jul 18 '05 #6

 P: n/a On Fri, 23 Jul 2004, Tim Peters wrote: If you view a floating-point number as being exactly what it says it is, then I have a proof that 1==2 to show you... ;) Jul 18 '05 #7

 P: n/a Helmut Jarausch wrote in message news:<41**************@igpm.rwth-aachen.de>... .... If your input is in degrees, define def mysin(x) return math.sin(x/pi*180) # 1 degree = 180/pi radians (don's use x/180*pi) now print mysin(32) gives 0.529919264233 x/180*pi _is_ correct. Your formula gives mysin(32) = -0.9408618465702292. Btw, another way to write this is: def mysin(x): return math.sin(math.radians(x)) Jul 18 '05 #8

 P: n/a da*****@yahoo.com (Dan Bishop) wrote in message news:... Helmut Jarausch wrote in message news:<41**************@igpm.rwth-aachen.de>... ... If your input is in degrees, define def mysin(x) return math.sin(x/pi*180) # 1 degree = 180/pi radians (don's use x/180*pi) now print mysin(32) gives 0.529919264233 x/180*pi _is_ correct. Your formula gives mysin(32) = -0.9408618465702292. Btw, another way to write this is: def mysin(x): return math.sin(math.radians(x)) Even better: def mysin(x): return math.sin(math.radians(x % 360)) Jul 18 '05 #9

 P: n/a da*****@yahoo.com (Dan Bishop) wrote in message news:... Helmut Jarausch wrote in message news:<41**************@igpm.rwth-aachen.de>... ... If your input is in degrees, define def mysin(x) return math.sin(x/pi*180) # 1 degree = 180/pi radians (don's use x/180*pi) now print mysin(32) gives 0.529919264233 x/180*pi _is_ correct. Your formula gives mysin(32) = -0.9408618465702292. Btw, another way to write this is: def mysin(x): return math.sin(math.radians(x)) Even better: def mysin(x): return math.sin(math.radians(x % 360)) Jul 18 '05 #10

 P: n/a On 23 Jul 2004 23:00:18 -0700, da*****@yahoo.com (Dan Bishop) wrote: da*****@yahoo.com (Dan Bishop) wrote in message news:... def mysin(x): return math.sin(math.radians(x)) Even better: def mysin(x): return math.sin(math.radians(x % 360)) Why? for x in range( 20 ): print '%.12f %.12f' % (math.sin( math.radians( x ) ), math.sin( math.radians( x % 360 ) )) 0.000000000000 0.000000000000 0.017452406437 0.017452406437 0.034899496703 0.034899496703 0.052335956243 0.052335956243 0.069756473744 0.069756473744 0.087155742748 0.087155742748 0.104528463268 0.104528463268 0.121869343405 0.121869343405 0.139173100960 0.139173100960 0.156434465040 0.156434465040 0.173648177667 0.173648177667 0.190808995377 0.190808995377 0.207911690818 0.207911690818 0.224951054344 0.224951054344 0.241921895600 0.241921895600 0.258819045103 0.258819045103 0.275637355817 0.275637355817 0.292371704723 0.292371704723 0.309016994375 0.309016994375 0.325568154457 0.325568154457 Regards, Dan -- Dan Sommers Never play leapfrog with a unicorn. Jul 18 '05 #11

 P: n/a Frank Millman wrote: Hi all I was helping my niece with her trigonometry homework last night. Her calculator's batteries were flat, so I thought I would use Python's math module to calculate sin, cos, and tan. Can someone please explain these discrepancies? Thank you so much for the explanations, everyone. I appreciate your patience. I agree with Timothy's suggestion about adding a note to the documentation. Obviously the math module is designed for those that know what they are doing. However, you will always get the odd guy like me that has some vague recollection of trigonometry from school days, but does not really understand it, so it should help to avoid similar confusion in the future. Frank Jul 18 '05 #12

 P: n/a Dan Sommers wrote: On 23 Jul 2004 23:00:18 -0700, da*****@yahoo.com (Dan Bishop) wrote: def mysin(x): return math.sin(math.radians(x % 360)) Why?for x in range( 20 ): print '%.12f %.12f' % (math.sin( math.radians( x ) ), math.sin( math.radians( x % 360 ) )) 0.000000000000 0.000000000000 0.017452406437 0.017452406437 0.034899496703 0.034899496703 0.052335956243 0.052335956243 0.069756473744 0.069756473744 0.087155742748 0.087155742748 0.104528463268 0.104528463268 0.121869343405 0.121869343405 0.139173100960 0.139173100960 0.156434465040 0.156434465040 0.173648177667 0.173648177667 0.190808995377 0.190808995377 0.207911690818 0.207911690818 0.224951054344 0.224951054344 0.241921895600 0.241921895600 0.258819045103 0.258819045103 0.275637355817 0.275637355817 0.292371704723 0.292371704723 0.309016994375 0.309016994375 0.325568154457 0.325568154457 for x in range(10000000, 10000020): print '%.12f %.12f' % (math.sin( math.radians( x ) ), math.sin( math.radians( x % 360 ) )) -0.984807753010 -0.984807753012 -0.981627183449 -0.981627183448 -0.978147600733 -0.978147600734 -0.974370064789 -0.974370064785 -0.970295726278 -0.970295726276 -0.965925826288 -0.965925826289 -0.961261695942 -0.961261695938 -0.956304755964 -0.956304755963 -0.951056516293 -0.951056516295 -0.945518575604 -0.945518575599 -0.939692620787 -0.939692620786 -0.933580426495 -0.933580426497 -0.927183854571 -0.927183854567 -0.920504853453 -0.920504853452 -0.913545457639 -0.913545457643 -0.906307787041 -0.906307787037 -0.898794046299 -0.898794046299 -0.891006524183 -0.891006524188 -0.882947592863 -0.882947592859 -0.874619707138 -0.874619707139 When the numbers get larger, floats start losing precision. If you restrict the numbers to the range [0, 360[ before conversion to radians (and hence to degrees), that problem doesn't exist. -- "Codito ergo sum" Roel Schroeven Jul 18 '05 #13

 P: n/a Roel Schroeven wrote: When the numbers get larger, floats start losing precision. If you restrict the numbers to the range [0, 360[ before conversion to radians (and hence to degrees), that problem doesn't exist. (360**100 +0.0) % 360 184.0 Rule of thumb: floats are always inaccurate. % may only help when you are dealing with large integers denoting an angle in degrees - an unlikely scenario methinks. Peter Jul 18 '05 #14

 P: n/a Peter Otten wrote: Roel Schroeven wrote:When the numbers get larger, floats start losing precision. If yourestrict the numbers to the range [0, 360[ before conversion to radians(and hence to degrees), that problem doesn't exist.(360**100 +0.0) % 360 184.0 Rule of thumb: floats are always inaccurate. % may only help when you are dealing with large integers denoting an angle in degrees - an unlikely scenario methinks. Ok, you're right, I only considered the case where the input is specified in degrees. Anyway, when dealing with angles it's in most cases very well possible to keep the values small by doing % 360 or % (2*pi) in all relevant operations on the angles. -- "Codito ergo sum" Roel Schroeven Jul 18 '05 #15

 P: n/a Dan Sommers wrote in message news:... On 23 Jul 2004 23:00:18 -0700, da*****@yahoo.com (Dan Bishop) wrote: da*****@yahoo.com (Dan Bishop) wrote in message news:... def mysin(x): return math.sin(math.radians(x)) Even better: def mysin(x): return math.sin(math.radians(x % 360)) Why? for x in range( 20 ): print '%.12f %.12f' % (math.sin( math.radians( x ) ), math.sin( math.radians( x % 360 ) )) [2 identical columns] It's not suprising that they're identical: When 0 <= x < 360, then x % 360 == x. However, x = 360000000000L # a billion revolutions math.sin(math.radians(x)) -6.6394736764063769e-08 math.sin(math.radians(x % 360)) 0.0 Jul 18 '05 #16

 P: n/a On 24 Jul 2004 12:44:30 -0700, da*****@yahoo.com (Dan Bishop) wrote: Dan Sommers wrote in message news:... On 23 Jul 2004 23:00:18 -0700, da*****@yahoo.com (Dan Bishop) wrote: > da*****@yahoo.com (Dan Bishop) wrote in message news:... >> def mysin(x): >> return math.sin(math.radians(x)) > Even better: > def mysin(x): > return math.sin(math.radians(x % 360)) Why? >>> for x in range( 20 ): print '%.12f %.12f' % (math.sin( math.radians( x ) ), math.sin( math.radians( x % 360 ) )) [2 identical columns] It's not suprising that they're identical: When 0 <= x < 360, then x % 360 == x. Yes, obviously, no surprise there. Duh! (smacks self on forehead) I do, hoever, agree with Peter Otten about very large integers denoting angles in degreen being unlikely. Usually, the 'mod 2pi' ends up in the calculation of the angle rather than in the call to math.. Regards, Dan -- Dan Sommers Never play leapfrog with a unicorn. Jul 18 '05 #17

This discussion thread is closed

Replies have been disabled for this discussion. 