How do I avoid catastrophic cancellation for small numbers in f(x) = (1-cos(x))/x**2 in Python 3.7?
This is what I tried so far (the key, I know, is some trigonometric identity that enables you to avoid the cancellation, and I also know, having used L'Hopital's rule, that the limit→0 for f(x) is 0.5, so the correct program output is something very close to 0.5, which is what you do get if you use x = 1.2e-4 for example, but you get cancellation with smaller numbers like 1.2e-8, and I need to make it so this doesn't happen).
from math import *
def f(x): #these are all the same function using different identities
a = (1-(sin(x)/tan(x)))/(x**2)
b = (1-(sin(2*x)/(2*sin(x))))/(x**2)
c = (1-((1-((tan(x/2))**2))/(1+(tan(x/2))**2)))/(x**2)
d = (sin(x)**2+cos(x)**2-cos(x))/(x**2)
e = (sin(x)**2+cos(x)**2-(sin(2*x)/(2*sin(x))))/(x**2)
return a, b, c, d, e
print(k(1.2e-8))
#Output: (0.0, 0.7709882115452477, 0.0, 0.0, 0.0) - whereas need 0.5000...
Like this:
sin(x)/x * tan(x/2)/x
It does the job right up to the end, x = 1e-308 is still OK.
Unfortunately I cannot offer much insight into why it works well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With