alexbarry / AlexCalc

Scientific calculator with LaTeX equation display, variables, units, complex numbers. Runs locally in your browser with WebAssembly.
Other
22 stars 1 forks source link

sin(pi) not equal to 0? #16

Open jpggithub opened 3 months ago

jpggithub commented 3 months ago

Perhaps I missed something. With "radian" activated, sin(pi) gives = 1.224646799 \cdot 10^{-16} It should give 0?

alexbarry commented 3 months ago

TL;DR: I could simply round the output of the trig functions down to zero if it is less than ~1e-15 or so. In fact I already started doing this in a pull request that I haven't merged yet, since it also adds another feature, and I wanted to make sure both the feature and this rounding worked well. Otherwise, what you're seeing is the same as calculating sin(pi) in plain C code, which is a number very close to zero, and within the rounding error that computers can introduce.

You're right, sin(pi) should be zero (as long as you're in radian mode). What you're seeing is a number very close to zero. It is simply the result of computers not having finite precision. I think doubles (the way I'm handling floating point values in my code) only have around 16 digits of precision anyway. If you just compute sin(pi) in basic C code:

#include <stdio.h>
#include <math.h>

int main(void) {
    long double x = M_PI;
    printf("pi       = %Le\n",  x);
    printf("sin(pi)  = %e\n",  sin(x));
    printf("sinl(pi) = %Le\n", sinl(x));

    return 0;
}

Output:

pi       = 3.141593e+00
sin(pi)  = 1.224647e-16
sinl(pi) = 1.224647e-16

I had planned on simply rounding the output of the trig functions to zero if it is less than some threshold, see this commit in this pull request. But I should also probably do that for some of the polar complex number math. But I need to be careful here, because by doing this, we're losing precision for very small values. For example, what should sin(pi + 2e-16) output? I believe that sin(x) is approximately x for small values (and sin(n*pi + x) is probably similar, being close to x or -x). This would artificially force the output to be zero for a wider range around every zero crossing. We're flattening the sine curve for a small range around the zero crossings.

But it is probably worth it overall, just to avoid seeing the big messy ~1e-16 result when performing basic calculations like sin(pi). (It is even worse with complex numbers. e^(i*pi) + 1 is supposed to be one of the most "beautiful" equations in math, or something like that, and in mine it outputs a+i*b where a and b are around the 1.224e-16 value that you're seeing for sin(pi). This I need to handle even more carefully, since I still want to support e^x for very small values of x (for trig this probably doesn't matter as much).

Anyway, what do you think? Does rounding the output of the trig functions (if less than 1e-15) to zero seem reasonable? It seems much better to have nice looking outputs for sin(n*pi), and losing a bit of precision for sin(n*pi + small) probably doesn't matter. I assume values of less than 1e-15 are basically insignificant for angles when doing trig.

jpggithub commented 3 months ago

Thank you for your detailed answer. I must say that I don't know what to tell you as I am not a dev myself. Personally I would look at what other similar software do (for instance https://f-droid.org/fr/packages/org.solovyev.android.calculator/ that I use myself and give sin(pi)=0). Regards