# Why are transcendental functions of large numbers inaccurate on computers?

For instance, why is it hard to accurately compute sin(1e99)? I suspect it has something to do with rounding error.

• log(1e99) is fairly simple though ;) Oct 14 '15 at 9:04
• I don't agree with the title, as this isn't true for all transcendental functions (f.i. the logarithm and exponential have no such issue). It's probably more characteristic of oscillating functions. Oct 14 '15 at 9:05
• @YvesDaoust: I'd argue that the problem is fairly general. The logarithm is in fact the main exception, as the usual floating-point representation explicitly stores an exponent. And exp(x) can be approximated by exp(x/2) ^ 2. That said, any function that doesn't oscillate tends to have an asymptote or go to infinity, both of which make the implementation for large arguments trivial. Oct 14 '15 at 9:17

There's nothing fundamentally hard about computing $\sin(10^{99})$. You simply compute $x = 10^{99} \bmod 2\pi$, then compute $\sin(x)$. (Why is this valid? It's because $\sin(x)=\sin(y)$ if $x\equiv y \pmod{2\pi}$.) It's not too hard to compute $x$ if you use a numerical representation that has enough digits of precision, and then to compute $\sin(x)$ using standard methods.

However, a standard double won't have enough precision to perform this computation. It only has about 53 bits of precision; that's a lot less than the $99 \lg 10 \approx 329$ bits of precision you'd need to be able to distinguish $10^{99}$ from $10^{99}+1$. (A standard IEEE float cannot even represent values in excess of $3*10^{38}$). Of course, $\sin(10^{99})$ is very different from $\sin(10^{99}+1)$. So, if you want to compute $\sin(10^{99})$, just stuffing $10^{99}$ into a float or double and then trying to invoke the $\sin(\cdot)$ function on that is not going to end well.

If you want to compute $x$ to at least $b$ bits of precision, you'll probably need a numerical representation that can represent $10^{99}$ to at least $329+b$ bits of precision (probably more than that, for intermediate values that arise during the modular reduction). A float or double ain't gonna be enough for that.

• Having implemented sin(x) myself (embedded platform), I can confirm sin(10^99) is easy. You need to check the exponent anyway, and for this case just return 0. The hard parts are around 2^24 (16 million) where the Least Significant Bit is in the order of π. Oct 14 '15 at 7:41
• @MSalters "just return 0" -- are you claiming that $\sin(10^{99})=0$? That can't be correct, since $10^{99}$ isn't a multiple of $\pi$. If that's not what you're claiming, I don't understand your comment. Oct 14 '15 at 8:39
• @DavidRicherby: obviously standard floating-point implementations cannot compute $\sin(10^{99})$ with a single significant digit, as they are just unable to represent that number. Hence returning $0$ isn't worse than any other value. Oct 14 '15 at 8:54
• @DavidRicherby: 10^99 isn't even exactly representable in double precision. The actual number passed to sin(x) will be a 53 bit approximation (so about 16 digits), approximately 1.8287798260516400 * 2^328. The rounding error there is about 0.00000000000000000003 * 2^238, which is far, far larger than π. Oct 14 '15 at 8:54
• @DavidRicherby: The actual implementation is if input.exponent > 26 return 0.0. When the possible rounding error exceeds the 2π period, the output is fully dependent on that unknown rounding error. 0 is simply the mean value of sin(x). Oct 14 '15 at 9:27

Taking the sine of large numbers is a numerically unstable operation.

Considering an argument like $10^{99}$, you can get a completely different value of the sine by adding, say $1$ to it. Think that this is a relative change of $10^{-99}$ !

Indeed, $$|\sin(a+1)-\sin(a)|=|2\sin(\frac12)\cos(a+\frac12)|>0.95|\sin(a+\frac12)|,$$

so that you can find arbitrarily tiny $\epsilon=\dfrac1a$ such that

$$|\sin(a(1+\epsilon))-\sin(a)|>0.5.$$