1 2 /** 3 * @name CeL polynomial function 4 * @fileoverview 5 * 本檔案包含了數學多項式的 functions。 6 * @since 7 */ 8 9 10 if (typeof CeL === 'function'){ 11 12 /** 13 * 本 module 之 name(id),<span style="text-decoration:line-through;">不設定時會從呼叫時之 path 取得</span>。 14 * @type String 15 * @constant 16 * @inner 17 * @ignore 18 */ 19 var module_name = 'math.polynomial'; 20 21 //=================================================== 22 /** 23 * 若欲 include 整個 module 時,需囊括之 code。 24 * @type Function 25 * @param {Function} library_namespace namespace of library 26 * @param load_arguments 呼叫時之 argument(s) 27 * @return 28 * @name CeL.math.polynomial 29 * @constant 30 * @inner 31 * @ignore 32 */ 33 var code_for_including = function (library_namespace, load_arguments) { 34 35 36 var 37 /** 38 * null module constructor 39 * @class 數學多項式相關之 function。 40 * @constructor 41 */ 42 CeL.math.polynomial 43 = function () { 44 // null module constructor 45 }; 46 47 /** 48 * for JSDT: 有 prototype 才會將之當作 Class 49 */ 50 CeL.math.polynomial 51 .prototype = {}; 52 53 54 55 56 57 // polynomial ----------------------------------- 58 59 /* 60 return [r1,r2,..[,餘式]] 61 ** 若有無法解的餘式,會附加在最後! 62 63 高次代數方程數值求根解法: http://www.journals.zju.edu.cn/sci/2003/200303/030305.pdf http://tsg.gxtvu.com.cn/eduwest/web_courseware/maths/0092/2/2-3.htm 64 修正牛頓法 1819年霍納法 伯努利法 勞思表格法 http://en.wikipedia.org/wiki/Ruffini%27s_rule 65 Newton's method牛頓法 x2=x1-f(x1)/f'(x1) http://zh.wikipedia.org/wiki/%E7%89%9B%E9%A1%BF%E6%B3%95 66 四次方程Finding roots http://zh.wikipedia.org/wiki/%E5%9B%9B%E6%AC%A1%E6%96%B9%E7%A8%8B 67 一元三次方程的公式解 http://en.wikipedia.org/wiki/Cubic_equation http://math.xmu.edu.cn/jszg/ynLin/JX/jiaoxueKJ/5.ppt 68 69 var rootFindingFragment=1e-15; // 因為浮點乘除法而會產生的誤差 70 */ 71 rootFinding[generateCode.dLK]='rootFindingFragment'; 72 function rootFinding(polynomial){ 73 var r=[],a,q; 74 75 //alert(NewtonMethod(polynomial)); 76 77 while(a=polynomial.length,a>1){ 78 if(a<4){ 79 if(a==2)r.push(-polynomial[1]/polynomial[0]); 80 else{ 81 a=polynomial[1]*polynomial[1]-4*polynomial[0]*polynomial[2]; // b^2-4ac 82 q=2*polynomial[0]; 83 if(a<0)a=(Math.sqrt(-a)/Math.abs(q))+'i',q=-polynomial[1]/q,r.push(q+'+'+a,q+'-'+a); 84 else a=Math.sqrt(a)/q,q=-polynomial[1]/q,r.push(q+a,q-a); 85 } 86 polynomial=[];break; 87 }else if(a=NewtonMethod(polynomial),Math.abs(a[1])>rootFindingFragment){ 88 //alert('rootFinding: NewtonMethod 無法得出根!\n誤差:'+a[1]); 89 break; 90 } 91 a=qNum(a[0],1e6);//alert(a[0]+'/'+a[1]); 92 q=pLongDivision(polynomial,[a[1],-a[0]]); 93 if(Math.abs(q[1][0])>pLongDivisionFragment){alert('rootFinding error!\n誤差:'+q[1][0]);break;} 94 r.push(a[0]/a[1]),polynomial=q[0]; 95 //alert('get root: '+a[0]+'\n'+polynomial); 96 } 97 98 if(polynomial.length==5){ // 兩對共軛虛根四次方程 99 q=[],a=polynomial.length,i=0; 100 while(--a)q.push(polynomial[i++]*a); // 微分 101 if(q=rootFinding(q),q.length>1){ 102 //a=0;for(var i=0;i<polynomial.length;i++)a=a*q[0]+polynomial[i]; 103 // 將函數上下移動至原極值有根處,則會有二重根。原函數之根應為(-b +- (b^2-4ac)^.5)/2a,則此二重根即為-b/2a(?) 104 // 故可將原函數分解為(x^2-2*q[n]*x+&)(?x^2+?x+?) 105 // 以長除法解之可得&有三解:a*&^2+(-2*q[n]*(b+2*a*q[n])-c)*&+e=0 or .. 106 q=q[0],a=4*polynomial[0]*q+polynomial[1]; 107 if(a==0){a=rootFinding([polynomial[0],-2*q*(polynomial[1]+2*q*polynomial[0])-polynomial[2],polynomial[4]]);if(a.length<2)a=null;else a=a[0];} 108 else a=(2*polynomial[2]*q+polynomial[3]-2*polynomial[0]*q*(2*polynomial[0]*q+polynomial[1]))/a; 109 var o; 110 if(!isNaN(a)&&(q=pLongDivision(polynomial,o=[1,-2*q,a]),Math.abs(q[1][0])<pLongDivisionFragment&&Math.abs(q[1][1])<pLongDivisionFragment)) 111 a=rootFinding(q[0]),r.push(a[0],a[1]),a=rootFinding(o),r.push(a[0],a[1]),polynomial=[]; 112 } 113 } 114 115 if(polynomial.length>1){ 116 r.push(polynomial); 117 //if(polynomial.length%2==1)alert('rootFinding error!'); 118 } 119 return r; 120 } 121 //alert(rootFinding(getPbyR([1,4/3,5,2,6])).join('\n')); 122 //alert(NewtonMethod(getPbyR([1,4,5,2,6])).join('\n')); 123 //alert(rootFinding([1,4,11,14,10]).join('\n')); 124 //alert(rootFinding([1,2,3,2,1]).join('\n')); 125 126 /* 長除法 polynomial long division http://en.wikipedia.org/wiki/Polynomial_long_division 2005/3/4 18:48 127 dividend/divisor=quotient..remainder 128 129 input (dividend,divisor) 130 return [商,餘式] 131 132 var pLongDivisionFragment=1e-13; // 因為浮點乘除法而會產生的誤差 133 */ 134 pLongDivision[generateCode.dLK]='pLongDivisionFragment'; 135 function pLongDivision(dividend,divisor){ 136 if(typeof dividend!='object'||typeof divisor!='object')return; 137 while(!dividend[0])dividend.shift();while(!divisor[0])dividend.shift(); 138 if(!dividend.length||!divisor.length)return; 139 140 var quotient=[],remainder=[],r,r0=divisor[0],c=-1,l2=divisor.length,l=dividend.length-l2+1,i; 141 for(i=0;i<dividend.length;i++)remainder.push(dividend[i]); 142 while(++c<l) 143 for(quotient.push(r=remainder[c]/r0),i=1;i<l2;i++){ 144 remainder[c+i]-=r*divisor[i]; 145 //if(Math.abs(remainder[c+i])<Math.abs(.00001*divisor[i]*r))remainder[c+i]=0; 146 } 147 return [quotient,remainder.slice(l)]; 148 } 149 //alert(pLongDivision([4,-5,3,1/3+2/27-1],[3,-1]).join('\n')); 150 151 /* 152 // polynomial multiplication乘法 153 function polynomialMultiplication(pol1,pol2){ 154 //for() 155 } 156 */ 157 158 /* Newton Iteration Function 2005/2/26 1:4 159 return [root,誤差] 160 */ 161 function NewtonMethod(polynomial,init,diff,count){ 162 var x=0,d,i,t,l,o,dp=[]; 163 if(!polynomial||!(d=l=polynomial.length))return; 164 while(--d)dp.push(polynomial[x++]*d); // dp:微分derivative 165 if(!diff)diff=rootFindingFragment;diff=Math.abs(diff); 166 if(!count)count=15; 167 x=init||0,o=diff+1,l--; 168 //alert(polynomial+'\n'+dp+'\n'+diff+',l:'+l); 169 while(o>diff&&count--){ 170 //alert(count+':'+x+','+d); 171 for(d=t=i=0;i<l;i++)d=d*x+polynomial[i],t=t*x+dp[i]; 172 d=d*x+polynomial[l]; 173 //alert(d+'/'+t); 174 if(t)d/=t;else d=1;//alert(); 175 t=Math.abs(d); 176 if(o<=t)if(o<rootFindingFragment)break;else x++; // test 177 o=t,x-=d; 178 } 179 return [x,d]; 180 } 181 182 // 從roots得到多項式 2005/2/26 0:45 183 function getPbyR(roots){ 184 var p,r,i,c=0,l; 185 if(!roots||!(l=roots.length))return; 186 p=[1,-roots.pop()]; 187 while(++c<l) 188 if(r=roots.pop()){p.push(-r*p[i=c]);while(i)p[i]-=p[--i]*r;} 189 else p.push(0); 190 return p; 191 } 192 193 //alert(getPbyR([1,2,3])); 194 //document.write(Newton1(getPbyR([2,32,5,3]))); 195 196 // ↑polynomial ----------------------------------- 197 198 199 200 201 202 return ( 203 CeL.math.polynomial 204 ); 205 }; 206 207 //=================================================== 208 209 CeL.setup_module(module_name, code_for_including); 210 211 }; 212