├── README.md ├── Utils.js └── calcuUtils.js /README.md: -------------------------------------------------------------------------------- 1 | # JavaScript-precision-algorithm -------------------------------------------------------------------------------- /Utils.js: -------------------------------------------------------------------------------- 1 | // JavaScript Document 2 | "use strict"; 3 | var Utils={}; 4 | if(!Utils){ 5 | Utils={}; 6 | } 7 | Utils.valid=(function(){ 8 | var valid={}; 9 | if(!valid){ 10 | valid={}; 11 | } 12 | valid.regExp=(function(){ 13 | var regExp={}; 14 | //匹配非负正数 15 | regExp.regExpNonNegtiveInt=/^[1-9]\d*|0$/; 16 | //匹配数字 17 | regExp.number=/^[\-]?([0]|[1-9][0-9]*)([\.][0-9]+)?$/; 18 | //匹配含小数点的全零表达式,形如 0.00 19 | regExp.regExpZero=/^[0]+[\.][\d]+$/; 20 | //匹配不含小数点的全零表达式,形如 0.00 21 | regExp.regExpAllZero=/^[0]{1,}$/; 22 | //匹配表示零的数字 23 | regExp.regExpZero=/^[0]{1,}$|^[0]{1,}[\.][0]{1,}$/; 24 | //匹配javascript的指数表达式的数字 例如:-2.1e-15 1.5e+46 25 | regExp.lge=/^[\-]?[1-9][0-9]*([\.][0-9]*[1-9]+)?[e][\+|\-][1-9]+[0-9]*$/; 26 | //返回带有各种校验的数字正则对象 27 | return regExp; 28 | })(); 29 | valid.arrays=(function(){ 30 | //数组内部全部为数字 31 | var arrays={}; 32 | arrays.isAllNumber=function(array){ 33 | if(array instanceof Array){ 34 | for(var i=0;ib.length){ 82 | return true; 83 | }else if(a.lengthparseInt(b.substr(i,1),10)){ 88 | return true; 89 | }else if(parseInt(a.substr(i,1),10)1?baseNumArr[1].length:0; 124 | var power=tempArr[1].substr(1); 125 | var zerofill=""; 126 | for(var i=0;i=len2?len1-len2:len2-len1; 171 | var zeros=""; 172 | var result={}; 173 | for(var i=0;i=len2){//0.01,300 >>>1 ,30000 181 | result.str1=arr1[0]+arr1[1]; 182 | result.str2=arr2[0]+(arr2[1]?arr2[1]:"")+zeros; 183 | }else{ 184 | result.str1=arr1[0]+(arr1[1]?arr1[1]:"")+zeros; 185 | result.str2=arr2[0]+arr2[1]; 186 | } 187 | } 188 | var tempM=0,tempN=0,strM=result.str1,strN=result.str2; 189 | for(var m=0;m=len2?len1-len2:len2-len1; 214 | var result={}; 215 | var strM= arr1.length>1?arr1[0]+arr1[1]:arr1[0]; 216 | var strN= arr2.length>1?arr2[0]+arr2[1]:arr2[0]; 217 | result.str1=strM; 218 | result.str2=strN; 219 | 220 | result.le=len1+len2+n; 221 | //所有小数点位数 222 | result.sm=len1+len2; 223 | return result; 224 | } 225 | 226 | //被除数和除数的除法运算;被除数,除数 227 | Calculator.prototype._devidePower=function(dividend,divisor,n){ 228 | if(Utils.valid.regExp.regExpZero.test(dividend)){ 229 | return [0]; 230 | } 231 | var lazyN=false; 232 | if(!n && !Utils.valid.regExp.regExpNonNegtiveInt.test(n)){ 233 | n=12; 234 | lazyN=true; 235 | } 236 | var len=divisor.length; 237 | var num=parseInt(divisor,10); 238 | var flag=true;//当小数位数达到指定精度时,标记为false,退出循环体 239 | //定义除法轮次 240 | var i=0; 241 | //定义小数轮次,如果小数轮次和n相等,则退出循环 242 | var j=0; 243 | //定义小数点的标记,第一次满足添加小数点时标记 244 | var dotFlag=true; 245 | var result=[]; 246 | //初始化第一次被除数的最高几位数,做第一个轮次除法 247 | var subDivi=dividend.substr(0,len); 248 | while(flag){ 249 | //临时被除数,从最高位截取除数长度 250 | var temp=parseInt(subDivi,10); 251 | //余数 1=1%3 252 | var remainder=temp%num; 253 | //商 0=(1-1%3)/3 254 | var quotient =(temp-temp%num)/num; 255 | 256 | result.push(quotient); 257 | 258 | if(dividend.substr(i+len,1)===""){ 259 | if(remainder===0 && lazyN){ 260 | flag=false; 261 | }else{ 262 | if(dotFlag && n!=0){ 263 | result.push("."); 264 | dotFlag=false; 265 | } 266 | } 267 | subDivi=remainder+"0"; 268 | j++; 269 | }else{ 270 | subDivi=remainder+dividend.substr(len+i,1); 271 | } 272 | if(j===n+1){ 273 | flag=false; 274 | } 275 | i++; 276 | } 277 | return result; 278 | } 279 | 280 | //判断减法相减的结果的正负 281 | Calculator.prototype._sign=function(strNum1,strNum2){ 282 | var a=strNum1.split("-"); 283 | var b=strNum2.split("-"); 284 | if(a.length===b.length && a.length==2){ 285 | //结果为负数 286 | return false; 287 | }else if(a.length===b.length && a.length==1){ 288 | //结果为正数 289 | return true; 290 | }else if(a.length!==b.length && a.length===1){ 291 | ////a>=0,b<0 292 | if(a[0]>=b[1]){ 293 | return true; 294 | }else if(a[0]=0 299 | if(a[1]>=b[0]){ 300 | return false; 301 | }else if(a[1]0;i--){ 314 | if(a[i]!=="."){ 315 | var m=a[i]+b[i]; 316 | if(m>9){ 317 | if(a[i-1]==="."){ 318 | a[i-2]=a[i-2]+1; 319 | }else{ 320 | a[i-1]=a[i-1]+1; 321 | } 322 | 323 | result.splice(0,0,m-10); 324 | }else{ 325 | result.splice(0,0,m); 326 | } 327 | }else{ 328 | result.splice(0,0,"."); 329 | } 330 | } 331 | if(a[0]+b[0]>9){ 332 | result.splice(0,0,a[0]+b[0]-10); 333 | result.splice(0,0,1); 334 | }else{ 335 | result.splice(0,0,a[0]+b[0]); 336 | } 337 | return result; 338 | } 339 | 340 | //无符号两个相同长度的数组相减 341 | Calculator.prototype._minusArr=function(arr1,arr2){ 342 | var a=arr1.slice(0); 343 | var b=arr2.slice(0); 344 | var len=arr1.length; 345 | var result=[]; 346 | if(this._compareArrABS(a,b)){ 347 | return this._minusArrUtils(a,b); 348 | }else{ 349 | return this._minusArrUtils(b,a); 350 | } 351 | } 352 | 353 | //两个相同长度的数组减,第一个参数绝对值比第二个绝对值大 354 | Calculator.prototype._minusArrUtils=function(arr1,arr2){ 355 | var a=arr1.slice(0); 356 | var b=arr2.slice(0); 357 | var len=arr1.length; 358 | var result=[]; 359 | for(var i=len-1;i>=0;i--){ 360 | var m=a[i]-b[i]; 361 | if(a[i]!=="."){ 362 | if(m<0){ 363 | if(a[i-1]==="."){ 364 | a[i-2]=a[i-2]-1; 365 | }else{ 366 | a[i-1]=a[i-1]-1; 367 | } 368 | result.splice(0,0,a[i]+10-b[i]); 369 | }else{ 370 | result.splice(0,0,m); 371 | } 372 | }else{ 373 | result.splice(0,0,"."); 374 | } 375 | } 376 | return result; 377 | } 378 | //把两个数字型字符串加工成相同长度的数组,小数点对齐 a:strNum1,b:strNum2 379 | Calculator.prototype._fillArrZero=function(strNum1,strNum2){ 380 | var result={}; 381 | var temp={}; 382 | var arr1=strNum1.split("."); 383 | var arr2=strNum2.split("."); 384 | var _a={}; 385 | var _b={}; 386 | var leftLen=arr1[0].length-arr2[0].length; 387 | if(leftLen>0){ 388 | arr2[0]=this._fillZero(leftLen)+arr2[0]; 389 | }else{ 390 | arr1[0]=this._fillZero(-leftLen)+arr1[0]; 391 | } 392 | _a.int=arr1[0].split(""); 393 | _b.int=arr2[0].split(""); 394 | if(arr1[1]||arr2[1]){ 395 | var aRight=arr1[1]?arr1[1]:""; 396 | var bRight=arr2[1]?arr2[1]:""; 397 | var rightLen=aRight.length-bRight.length; 398 | if(rightLen>0){ 399 | bRight+=this._fillZero(rightLen) 400 | }else{ 401 | aRight+=this._fillZero(-rightLen) 402 | } 403 | _a.decimal=aRight.split(""); 404 | _b.decimal=bRight.split(""); 405 | 406 | } 407 | temp.left=_a; 408 | temp.right=_b; 409 | if(temp.left.decimal){ 410 | result.arr1=temp.left.int.concat(".",temp.left.decimal); 411 | result.arr2=temp.right.int.concat(".",temp.right.decimal); 412 | }else{ 413 | result.arr1=temp.left.int; 414 | result.arr2=temp.right.int; 415 | } 416 | for(var i=0;i=0;i--){ 458 | var cur=result[0]; 459 | var temp=arr1[i]*n+cur; 460 | var rem=temp%10; 461 | result[0]=rem; 462 | var high=(temp-temp%10)/10; 463 | if(i===0 && high===0){ 464 | break; 465 | } 466 | result.splice(0,0,high); 467 | } 468 | return result; 469 | } 470 | //数组和数组相乘 471 | Calculator.prototype._arrMulti=function(multiplierArr,faciendArr){ 472 | var arr1=multiplierArr.slice(0); 473 | var arr2=faciendArr.slice(0); 474 | var len2=arr2.length,len1=arr1.length; 475 | var j=0,result="0"; 476 | var add=new Add(); 477 | for(var i=len2-1;i>=0;i--){ 478 | var zeros=[]; 479 | for(var k=0;k1?"-":""; 560 | var add=new Add(); 561 | if(n===0){ 562 | var arrZ=strNum1.split("."); 563 | if(arrZ.length==1 || parseInt(arrZ[1].substr(0,1),10)<5){ 564 | return arrZ[0]; 565 | }else{ 566 | return add.add(arrZ[0],sign+"1"); 567 | } 568 | } 569 | var zero="0.",one="0.",result; 570 | for(var i=0;i=5){ 584 | result=add.add(cut,sign+one).substring(0,at); 585 | }else{ 586 | result=temp.substring(0,at); 587 | } 588 | return result; 589 | } 590 | //给String 类扩展四舍五入方法 591 | String.prototype.toFixed=function(n){ 592 | var fix=new Fixed(); 593 | return fix.toFixed(this,n); 594 | } 595 | function Multiplication(){}; 596 | 597 | fnExtends(Multiplication,Calculator); 598 | 599 | Multiplication.prototype.multiply=function(strNum1,strNum2){ 600 | Calculator.call(this); 601 | strNum1=this._num2str(strNum1); 602 | strNum2=this._num2str(strNum2); 603 | if(!Utils.valid.regExp.number.test(strNum1) || !Utils.valid.regExp.number.test(strNum2)){ 604 | throw new Errors("参数不能被转化为有效的数字"); 605 | } 606 | var sign=this._mulSign(strNum1,strNum2) 607 | var a1=strNum1.split("-"); 608 | var a2=strNum2.split("-"); 609 | var s1=a1.length>1?a1[1]:a1[0]; 610 | var s2=a2.length>1?a2[1]:a2[0]; 611 | var temp=this._mulAmplify(s1,s2); 612 | var nArr1=[]; 613 | var result=this._arrMulti(this._parInt(temp.str1.split("")),this._parInt(temp.str2.split(""))); 614 | var n=temp.sm; 615 | var at=result.length-n; 616 | if(n===0){ 617 | return sign+result; 618 | } 619 | var left=result.substr(0,at); 620 | if(Utils.valid.regExp.regExpAllZero.test(left)){ 621 | left="0"; 622 | }else{ 623 | var count=0; 624 | var ar1=left.split(""); 625 | for(var i=0;i1?temp1[1]:temp1[0]; 658 | var t2=temp2.length>1?temp2[1]:temp2[0]; 659 | var temp=this._amplify(t1,t2); 660 | var a=temp.str1,b=temp.str2,t; 661 | var result=this._devidePower(a,b,n); 662 | if(result[0]===0 && result[1]!=="."){ 663 | result.splice(0,1) 664 | } 665 | return sign+result.join("") ; 666 | } 667 | //给String 类扩展除法,非常优雅 668 | String.prototype.divise=function(n){ 669 | var div=new Division(); 670 | var param=this.split(/[\/|÷]/); 671 | return div.divise(param[0],param[1],n); 672 | } 673 | //给Array 类扩展加法,非常优雅 674 | Array.prototype.add=function(stringObj){ 675 | obj="2*5+4"; 676 | if(this.length>0 && Utils.valid.arrays.isAllNumber(this)){ 677 | var add=new Add(); 678 | return add.add(this) 679 | } 680 | throw new Errors("数组元素有非数字元素"); 681 | } --------------------------------------------------------------------------------