jiggzson / nerdamer

a symbolic math expression evaluator for javascript
http://www.nerdamer.com
MIT License
515 stars 82 forks source link

defint(log(2cos(x/2)),-π,π,x) eval=> −0.012509423660499902 #336

Closed Happypig375 closed 6 years ago

Happypig375 commented 6 years ago

According to http://mathworld.wolfram.com/DefiniteIntegral.html, it should evaluate to 0.

jiggzson commented 6 years ago

There have been previous discussions regarding defint (see #96). I'm all open to suggestions.

Happypig375 commented 6 years ago

I'm all open to suggestions.

I suggest that this is a bug and should be fixed.

jiggzson commented 6 years ago

I seriously hope you're joking here. I'm not asking you to state the obvious. I'm asking for suggestions as to how to approach this. Again, I hope you're joking.

Happypig375 commented 6 years ago

Quick check: Algebrite's implementation returns 0.

Happypig375 commented 6 years ago

2nd quick check:

(function(f, l, u, dx) {
                dx = dx || 0.001; //default width of dx
                var n, sum, x0, x1, a, la, chg;
                n = (u-l)/dx;// number of trapezoids
                sum = 0; //area
                chg = 0; //track the change
                a = 0;
                for (var i=1; i<=n; i++) {
                    //the x locations of the left and right side of each trapezpoid
                    x0 = l + (i-1)*dx;
                    x1 = l + i*dx;
                    a = dx * (f(x0) + f(x1))/ 2; //the area
                    sum += a;
                } 
                //avoid errors with numbers around -1e-14;
                sum = Math.round(sum, 13);
                return sum;
            })(function(x){return Math.log(2*Math.cos(x/2));},-Math.PI,Math.PI)

The above function copied from core.Math2.num_integrate returns 0. So the algorithm is correct. Where is the bug?

jiggzson commented 6 years ago

defint(log(cos(x/2)),-pi,pi)

Wolfram Alpha: -4.35517 Algebrite: 0
Nerdamer: −4.3675531591186

Some error which may be remedied by the size of the mesh.

Happypig375 commented 6 years ago

3rd quick check: There was an error in the 2nd quick check. I should have used Number.toPrecision instead of Math.round. Sorry!

(function(f, l, u, dx) {
                dx = dx || 0.001; //default width of dx
                var n, sum, x0, x1, a, la, chg;
                n = (u-l)/dx;// number of trapezoids
                sum = 0; //area
                chg = 0; //track the change
                a = 0;
                for (var i=1; i<=n; i++) {
                    //the x locations of the left and right side of each trapezpoid
                    x0 = l + (i-1)*dx;
                    x1 = l + i*dx;
                    a = dx * (f(x0) + f(x1))/ 2; //the area
                    sum += a;
                } 
                //avoid errors with numbers around -1e-14;
                sum = sum.toPrecision(13);
                return sum;
            })(function(x){return Math.log(2*Math.cos(x/2));},-Math.PI,Math.PI)

It returns -0.01250942366046. So the bug IS here.

jiggzson commented 6 years ago

I'm guessing that Algebrite probably applies a symmetry test and then returns zero based on that. If you're familiar with their source code can you confirm? If that's the case then I'm curious why Wolfram Alpha returns -4.35517 for defint(log(cos(x/2)),-pi,pi) since the function appears symmetric around 0.

Happypig375 commented 6 years ago

First help wanted label ever :laughing: :tada:

jiggzson commented 6 years ago

I found this (https://github.com/scijs/integrate-adaptive-simpson) hidden beauty that seems to solve our problems. It replaces the existing defint function.

jiggzson commented 6 years ago

Fixed on dev branch.

Happypig375 commented 6 years ago

@jiggzson defint(sqrt(1+x^2),-1,1) eval=> 1.762747174039085896900904314654630624291 should=> 2.295587149392638074034298 GG.