/*
*/ // var polsol={versione:"20170221",tartaglia:1}; // polsol.polinomio=function(p,z){ // // z rappresenta la variabile indipendente e // puo' essere sia un numero che una Array, // z[0] rappresenta la parte reale del numero complesso // e z[1], se c'e' rappresenta la parte immaginaria. // // Il risultato e' sempre una Array di due elementi, // con l'elemento 0 parte reale e l'elemento 1 parte // immaginaria. // // Qui il polinomio ha come termine di grado 0 il // primo elemento, e l'ultimo elemento e' quello // di grado piu' elevato. // var x,y,rx,ry,rn,j; if(Array.isArray(z)){x=z[0]; if(z.length>1)y=z[1]; else{y=0}} else{x=z;y=0;} rx=1;ry=0; for(j=p.length-1;j>-1;j--){ if(Array.isArray(p[j])){rn=rx*x-ry*y+p[j][0]; if(p[j].length>1){ry=rx*y+ry*x+p[j][1];} else{ry=rx*y+ry*x;}} else{rn=rx*x-ry*y+p[j];ry=rx*y+ry*x;} rx=rn; } // // Un numero complesso e' indicato con [a,b] dove // a e b sono numeri reali e dunque e' una Array di // due elementi: l'elemento 0 e' la parte reale e // l'elemento 1 e' la parte immaginaria. // return [rx,ry]; }; // // Crea un polinomio di quarto grado di cui sa anche // le sue quattro radici e fa in modo che il termine // noto non possa mai essere esattamente nullo, // anche se piccolissimo. // Dati quattro argomenti reali calcola il polinomio // di quarto grado con 1 sottinteso come fattore // della quarta potenza. // polsol.perverifiche=function(a,bb,c,dd){ var b,d,pp,r1,r2,r3,r4,det; if(Math.abs(bb)==0)b=1.e-5; else b=bb; if(Math.abs(dd)==0)d=1.e-5; else d=dd; pp=[[b*d,0],[2*(a*d+b*c),0], [b+d+4*a*c,0],[2*(a+c),0]]; det=a*a-b; if(0>det){r1=[-a,Math.sqrt(-det)];r2=[-a,-Math.sqrt(-det)]} else{ r1=[-a+Math.sqrt(det),0];r2=[-a-Math.sqrt(det),0]} det=c*c-d; if(0>det){r3=[-c,Math.sqrt(-det)];r4=[-c,-Math.sqrt(-det)]} else{r3=[-c+Math.sqrt(det),0];r4=[-c-Math.sqrt(det),0]} return [pp,[r1,r2,r3,r4]]; } // // Equazione di secondo grado // polsol.secondogrado=function(r){ // // Radici equaz. di secondo grado a coeff. complessi: // (y + r[1] )*y + r[0] = 0 // // r[0][0] rappresenta la parte reale del termine noto. // r[0][1] e' la parte immaginaria del termine noto. // Se r[0] non e' una Array, r[0] e' il termine noto reale. // r[1][0] e' la parte reale del termine di primo grado. // r[1][1] e' la parte immaginaria del termine di primo grado. // Se r[1] non e' una Array r[1] e' il termine di primo grado reale. // Il termine di secondo grado e' sottinteso e vale 1. // var p,q,s,t,x,a,b; if(Array.isArray(r[0]))b=r[0]; else{b=[r[0],0]}; if(Array.isArray(r[1]))a=r[1]; else{a=[r[1],0]}; // if(0>=b[0]*b[0]+b[1]*b[1]) return [ [0,0],[-a[0],-a[1]] ]; p=a[0]*a[0]-a[1]*a[1]-4*b[0]; q=2*a[0]*a[1]-4*b[1]; with(Math) { if(p>0){ s=sqrt((sqrt(p*p+q*q)+p)*0.5); t=0.5*q/s; } else { t=sqrt((sqrt(p*p+q*q)-p)*0.5); // radici coincidenti if(0 >= t) return [[-a[0]/2,-a[1]/2],[-a[0]/2,-a[1]/2]]; s=0.5*q/t; } // Fa direttamente la radice di maggior modulo if(a[0]*s+a[1]*t>0) x=[-0.5*(a[0]+s), -0.5*(a[1]+t)]; else x=[-0.5*(a[0]-s), -0.5*(a[1]-t)]; // Deduce l'altra dal termine noto. p=1/( x[0]*x[0] + x[1]*x[1] ); } return [ x, [p*(b[0]*x[0]+b[1]*x[1]), p*(-b[0]*x[1]+b[1]*x[0])] ]; }; // // Equazione cubica. // polsol.cubica=function(poli){ // // radici di polinomio di terzo grado con // coefficienti reali. // Se il polinomio ha coefficienti con parte immaginaria la // parte immaginaria viene ignorata. // var p,q,r,a,b,d,aa,bb,rd,nr,psi; var an,sn,qn,pn,segno; if(3>poli.length) return [ [0,1],[0,1],[0,1] ]; if(Array.isArray(poli[2]))p=poli[2][0]; else{p=poli[2]}; if(Array.isArray(poli[1]))q=poli[1][0]; else{q=poli[1]}; if(Array.isArray(poli[0]))r=poli[0][0]; else{r=poli[0]}; a=(p*p-3*q)/9; b=(p*(9*q-2*p*p)-27*r)/54; d=b*b-a*a*a; // sn=p/3; qn=r-sn*(q-sn*(p-sn)); pn=q-sn*(2*p-3*sn); if(0>=pn*pn){ // cubo perfetto, tre radici coincidenti ! if(qn>0) segno=1; else if(0>qn) segno=-1; else segno=0; an=segno*Math.pow(Math.abs(qn),1/3)-sn; return [[an,0],[an,0],[an,0]];}; with(Math){ if(0>=d) { // Tre radici reali rd=sqrt(-d); nr=sqrt(-d+b*b); if(abs(b)>=rd) { psi=asin(rd/nr); if(0>b) psi=PI-psi; } else psi=acos(b/nr); aa=pow(nr,1/3); bb=aa*sin(psi/3); aa=aa*cos(psi/3); return [ [ 2*aa-p/3,0], [ bb*sqrt(3)-aa-p/3,0], [-bb*sqrt(3)-aa-p/3,0] ]; } else { // Una sola radice reale if(b>0) { aa = pow(sqrt(d)+b,1/3); bb = a/aa; } else { bb = -pow(sqrt(d)-b,1/3); aa = a/bb; } return [ [aa+bb-p/3,0], [-0.5*(aa+bb)-p/3,-0.5*sqrt(3)*(aa-bb)], [-0.5*(aa+bb)-p/3, 0.5*sqrt(3)*(aa-bb)] ]; }; }; }; // // Se la variabile tartaglia vale -1... // polsol.cubicabis=function(poli){ // // radici di polinomio di terzo grado con // coefficienti reali e calcolati con // algoritmo basato su funzioni trigonometriche // ed esponenziali var pp0,pp1,pp2; var a,p,q,s,am,bm,cm, dm, ca,sina,cosa,expa,segno,sqrt3; sqrt3=Math.sqrt(3); if(3>poli.length) return[ [0,1],[0,1],[0,1] ]; // Lo faccio uscire se il polinomio e' mal fatto. if(Array.isArray(poli[2]))pp2=poli[2][0]; else{pp2=poli[2]}; if(Array.isArray(poli[1]))pp1=poli[1][0]; else{pp1=poli[1]}; if(Array.isArray(poli[0]))pp0=poli[0][0]; else{pp0=poli[0]}; s=pp2/3; q=pp0-s*(pp1-s*(pp2-s)); p=pp1-s*(2*pp2-3*s); if(0>=p*p){ // cubo perfetto, tre radici coincidenti ! if(q>0) segno=1; else if(0>q) segno=-1; else segno=0; a=segno*Math.pow(Math.abs(q),1/3)-s; return [[a,0],[a,0],[a,0]];}; if(p>0){ bm=Math.sqrt(4*p/3); dm=-q*Math.sqrt(27/(4*p))/p; a=Math.log(dm+Math.sqrt(dm*dm+1))/3; expa=Math.exp(a); sina=bm*(expa-1/expa)/2; cosa=bm*(expa+1/expa)/2; return [[sina-s,0], [-sina/2-s,sqrt3*cosa/2], [-sina/2-s,-sqrt3*cosa/2]];}; // am=Math.sqrt(-4*p/3); cm=-q*Math.sqrt(-27/(4*p))/p; ca=Math.abs(cm); if(ca>1){ if(cm>0) segno=1; else if(0>cm) segno=-1; else segno=0; a=Math.log(ca+Math.sqrt(ca*ca-1))/3; expa=Math.exp(a); sina=segno*am*(expa-1/expa)/2; cosa=segno*am*(expa+1/expa)/2; return [[-cosa-s,0], [cosa/2-s,-sqrt3*sina/2], [cosa/2-s,sqrt3*sina/2]];}; // tre radici reali a=Math.asin(cm)/3; sina=am*Math.sin(a); cosa=am*Math.cos(a); return [[sina-s,0], [-sina/2+sqrt3*cosa/2-s,0], [-sina/2-sqrt3*cosa/2-s,0]]; }; // polsol.cubicarobusta=function(poli){ // radici di polinomio di terzo grado con // coefficienti reali. Calcolo preciso anche con // termine noto molto piccolo. var p,q,r,a,b,d,aa,bb,x1,x2,x3,rd,nr,psi; var an,sn,qn,pn,segno; if(3>poli.length) return [ [0,1],[0,1],[0,1] ]; if(Array.isArray(poli[2]))p=poli[2][0]; else{p=poli[2]}; if(Array.isArray(poli[1]))q=poli[1][0]; else{q=poli[1]}; if(Array.isArray(poli[0]))r=poli[0][0]; else{r=poli[0]}; // alert("In cubicarobusta"+" p= "+p+" q= "+q+" r= "+r); a=(p*p-3*q)/9; b=(p*(9*q-2*p*p)-27*r)/54; d=b*b-a*a*a; // sn=p/3; qn=r-sn*(q-sn*(p-sn)); pn=q-sn*(2*p-3*sn); if(0>=pn*pn){ // cubo perfetto, tre radici coincidenti ! if(qn>0) segno=1; else if(0>qn) segno=-1; else segno=0; an=segno*Math.pow(Math.abs(qn),1/3)-sn; return [[an,0],[an,0],[an,0]];}; with(Math){ if(0>d) { // Tre radici reali rd=sqrt(-d); nr=sqrt(-d+b*b); if(abs(b)>rd) { psi=asin(rd/nr); if(0>b) psi=PI-psi; } else psi=acos(b/nr); aa=pow(nr,1/3); bb=aa*sin(psi/3); aa=aa*cos(psi/3); x1=2*aa-p/3; x2=bb*sqrt(3)-aa-p/3; x3=-bb*sqrt(3)-aa-p/3; // if(!(!abs(x2)>abs(x1) || !abs(x3)>abs(x1))){ if(x2*x3!=0)x1=-r/(x2*x3);} // else if(!(!abs(x3)>abs(x2) || !abs(x1)>abs(x2))){ if(x1*x3!=0)x2=-r/(x1*x3);} // else if(!(!abs(x1)>abs(x3) || !abs(x2)>abs(x3))){ if(x1*x2!=0)x3=-r/(x1*x2);} // alert("Tre radici reali:\n"+x1+"\n"+x2+"\n"+x3); return [ [x1,0], [x2,0], [x3,0] ] } else { // Una sola radice reale if(b>0) { aa = pow(sqrt(d)+b,1/3); bb = a/aa; } else { bb = -pow(sqrt(d)-b,1/3); aa = a/bb; } x1=aa+bb-p/3; x2=-0.5*(aa+bb)-p/3; x3=-0.5*sqrt(3)*(aa-bb); if(x2*x2+x3*x3>x1*x1) x1=-r/(x2*x2+x3*x3); // alert("La radice reale e' una sola: "+x1); return [ [x1, 0], [x2, x3], [x2,-x3] ]; }; }; }; // // Equazione di quarto grado. // polsol.tetra=function(p){ // radici di polinomio di quarto grado con // coefficienti reali. var a,b,c,d,q,u,s,t,v,w,e,f,g,h,m,n; if(Array.isArray(p[3]))a=p[3][0]; else{a=p[3]}; if(Array.isArray(p[2]))b=p[2][0]; else{b=p[2]}; if(Array.isArray(p[1]))c=p[1][0]; else{c=p[1]}; if(Array.isArray(p[0]))d=p[0][0]; else{d=p[0]}; q=[[4*d*b-c*c-d*a*a,0],[c*a-4*d,0],[-b,0]]; if(polsol.tartaglia >0)u=polsol.cubica(q); else u=polsol.cubicabis(q); s=a*a/4+u[0][0]-b; t=u[0][0]*u[0][0]/4-d; with(Math){ v=abs(s); w=abs(t); if(w>v) { w=sqrt(w); v=(a*u[0][0]-2*c)/(4*w); } else if(v>w) { t=s; v=sqrt(v); w=(a*u[0][0]-2*c)/(4*v); } } if(t >= 0) { e=[u[0][0]/2-w,0]; f=[u[0][0]/2+w,0]; g=[a/2-v,0]; h=[a/2+v,0]; } else { e=[u[0][0]/2,w]; f=[u[0][0]/2,-w]; g=[a/2,-v]; h=[a/2,v]; } m=polsol.secondogrado([e,g]); n=polsol.secondogrado([f,h]); return [n[0],n[1],m[0],m[1]]; }; // polsol.tetrarobusta=function(p){ // // radici di polinomio di quarto grado con // coefficienti reali. Tratta bene il caso // del termine noto quasi nullo. // var a,b,c,d,q,r,s,t,u,v,w,e,f,g,h,m,n; if(Array.isArray(p[3]))a=p[3][0]; else{a=p[3]}; if(Array.isArray(p[2]))b=p[2][0]; else{b=p[2]}; if(Array.isArray(p[1]))c=p[1][0]; else{c=p[1]}; if(Array.isArray(p[0]))d=p[0][0]; else{d=p[0]}; // // Correzione empirica per evitare situazioni critiche. // Se d valesse esattamente 0 l'equazione sarebbe di // terzo grado e una radice nulla e se d valesse // esattamente 1 potrebbe essere una quarta potenza // della equazione z=1 cioe' quattro radici coincidenti // e problema simile se d valesse esattamente -1. // COMUNQUE IN QUESTI CASI SI OTTENGONO PRECISIONI PESSIME... // LE SOLUZIONI ANDREBBERO RAFFINATE ITERATIVAMENTE... // if(1.e-16>Math.abs(d))d=1.e-16; if(5.e-16>Math.abs(d-1))d=1+5.e-16; if(5.e-16>Math.abs(d+1))d=-1+5.e-16; // q=[[4*d*b-c*c-d*a*a,0],[c*a-4*d,0],[-b,0]]; if(polsol.tartaglia >0)u=polsol.cubicarobusta(q); else u=polsol.cubicabis(q); // alert("Trovo prima radice "+u[0]); r=u[0][0]; with(Math){ if(!(!(0>=abs(u[1][1])) || !(abs(u[1][0]) > abs(r)) )) r=u[1][0]; if(!(!(0>=abs(u[2][1])) || !(abs(u[2][0]) > abs(r)) )) r=u[2][0]; // s=a*a/4+r-b; t=r*r/4-d; v=abs(s); w=abs(t); if(w>v) { w=sqrt(w); v=(a*r-2*c)/(4*w); } else if(v>w) { v=sqrt(v); w=(a*r-2*c)/(4*v); } if( abs(r/2-w) > abs(r/2+w) ) { e=[r/2-w,0]; f=[d/e[0],0]; } else if( abs(r/2+w) > abs(r/2-w) ) { f=[r/2+w,0]; e=[d/f[0],0]; } else { e=[r/2-w,0]; f=[r/2+w,0]; } g=[a/2-v,0]; h=[a/2+v,0]; } m=polsol.secondogrado([e,g]); n=polsol.secondogrado([f,h]); return [n[0],n[1],m[0],m[1]]; }; // //Se si usa questa funzione fa prove a caso delle varie funzioni della libreria polsol
// polsol.provacaso=function(){ var j,n,z,xbr,poli=[],zeri=[]; var casi=[[2,polsol.secondogrado], [3,polsol.cubica],[3,polsol.cubicabis], [3,polsol.cubicarobusta],[4,polsol.tetra], [4,polsol.tetrarobusta]]; xbr="\u003cbr/\u003e"; n=Math.round(100*Math.random())%casi.length; for(j=0;casi[n][0]>j;j++)poli[j]= [Math.round(2000*Math.random()-1000),0]; if(n==0)poli[0][1]=Math.round(2000*Math.random()-1000); polsol.tartaglia=1-2*(Math.round(100*Math.random())%2); z=casi[n][1](poli); for(j=0;casi[n][0]>j;j++){ zeri[j]=polsol.polinomio(poli,z[j]) } return (xbr+"Esempio "+n+xbr+ "Polinomio: "+poli.join(";"+xbr)+ xbr+"Radici: "+z.join("; "+xbr)+ xbr+"Primo Zero: "+ zeri.join(xbr+"Altro Zero: ") ); } // //