JavaScript实现计算圆周率到小数点后100位的方法示例
程序员文章站
2022-06-24 23:07:06
本文实例讲述了javascript实现计算圆周率到小数点后100位的方法。分享给大家供大家参考,具体如下:
浮点数的有效数位是16位,我自己做了一个大数类,能存储100位...
本文实例讲述了javascript实现计算圆周率到小数点后100位的方法。分享给大家供大家参考,具体如下:
浮点数的有效数位是16位,我自己做了一个大数类,能存储100位有效数位,并实现了大数类的基本运算。我用它来计算圆周率(割圆法,即多边形逼近),得到了小数点后一百位有效数字,比对了machin 公式的计算结果,没有误差。用时约2秒。
完整示例如下:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>www.jb51.net js计算圆周率</title> </head> <body> <script> <!-- function bignum(str, n, b) { /* bignum -- 大数类 私有成员: data -- 119 位数字,放在长度为 17 的数组里,每个数组元素存放 7 位数字。 decimal_place -- 小数点的位置,从最左位开始算。 positive -- 是否是正数。 recalc() -- 为了尽可能存放最多的有效数位,去除前缀的 0,并重新计算小数点位置。 init() -- 部分初始化工作。 公有成员: bignum( string str, int n, bool b) -- 构造函数。参数:str -- 字符串,各个有效数位;n -- 整数,小数点位置,从最左位开始算,比如 bignum("123", 2) = 12.3; bignum("123", 0) = 0.123; bignum("123", -2) = 0.00123;b -- 布尔值,是否是正数。 add( bignum num ) -- 加法。 subtract( bignum num ) -- 减法。 multiply( bignum num ) -- 乘法。 divide( bignum num ) -- 除法。 squareroot() -- 平方根。 tostring() -- 转换为字符串(包括小数点),以便以文本形式输出计算结果。 clone() -- 复制。 */ this.recalc = function() /* 去除前缀的 0,并重新计算小数点位置 */ { for(var i = 0; i < 17; i ++) { if(this.data[0] != 0) break; this.data.shift(); this.data.push(0); this.decimal_place --; } } this.init = function() /* 部分初始化工作 */ { this.decimal_place = math.ceil( n / 7 ); //小数点位置 this.data = new array(17); //保存有效数位的数组 if(n % 7 > 0) { var arr = new array( 8 - n % 7 ); } else { var arr = new array( 1 - n % 7 ); } str = arr.join("0") + str; if(str.length > 119) { str = str.substr(0, 119); } else if(str.length < 119) { var arr = new array(120 - str.length); str += arr.join("0"); } for( var i = 0; i < 17; i ++ ) { this.data[i] = parseint( str.substr(i * 7, 7) , 10 ); } } /* 初始化开始 */ this.positive = b; if( ! /^0*$/.test(str) ) { this.init(); this.recalc(); } else { this.data = new array(17); for( var i = 0; i < 17; i ++ ) { this.data[i] = 0; } this.decimal_place = 0; } /* 初始化结束 */ this.add = function(num) /* 加法 */ { if(this.positive && !num.positive) { num.positive = true; var result = this.subtract(num); num.positive = false; return result; } else if(num.positive && !this.positive) { this.positive = true; var result = num.subtract(this); this.positive = false; return result; } var result = new bignum("", 0, this.positive); var num1,num2; if(this.decimal_place >= num.decimal_place) { num1 = this; num2 = num; } else { num1 = num; num2 = this; } result.decimal_place = num1.decimal_place; if(num1.decimal_place - num2.decimal_place >= 17) { for(var i = 0; i < 17; i ++) { result.data[i] = num1.data[i]; } return result; } var noffdec = num1.decimal_place - num2.decimal_place; var ntmp = 0; for( var i = 16; i >= 0; i -- ) { var ntmp1 = i - noffdec; var ntmp2 = 0; if(ntmp1 >= 0) { ntmp2 = num1.data[i] + num2.data[ntmp1]; } else { ntmp2 = num1.data[i]; } ntmp2 += ntmp; ntmp = math.floor(ntmp2 / 10000000); result.data[i] = ntmp2 % 10000000; } if(ntmp > 0) { result.data.unshift(ntmp); result.decimal_place ++; } return result; } this.subtract = function(num) /* 减法 */ { if(this.positive && !num.positive) { num.positive = true; var result = this.add(num); num.positive = false; return result; } else if(!this.positive && num.positive) { this.positive = true; var result = this.add(num); result.positive = false; this.positive = false; return result; } else { var num1 = num2 = null; var bpositive; if(this.decimal_place > num.decimal_place) { num1 = this; num2 = num; bpositive = this.positive; } else if(this.decimal_place < num.decimal_place) { num1 = num; num2 = this; bpositive = !this.positive; } else { for( var i = 0; i < 17; i ++ ) { if(this.data[i] > num.data[i]) { num1 = this; num2 = num; bpositive = this.positive; break; } else if(this.data[i] < num.data[i]) { num1 = num; num2 = this; bpositive = !this.positive; break; } } } if( num1 == null) { return new bignum("", 0, true); } else { if(num1.decimal_place - num2.decimal_place >= 17) { var result = new bignum("", 0, bpositive); for(var i = 0; i < 17; i ++) { result.data[i] = num1.data[i]; } result.decimal_place = num1.decimal_place; return result; } var result = new bignum("", 0, bpositive); result.decimal_place = num1.decimal_place; var noffdec = num1.decimal_place - num2.decimal_place; var ntmp = 0; for( var i = 16; i >= 0; i -- ) { var ntmp1 = i - noffdec; var ntmp2 = 0; if(ntmp1 >= 0) { ntmp2 = 10000000 + ntmp + num1.data[i] - num2.data[ntmp1]; } else { ntmp2 = 10000000 + ntmp + num1.data[i]; } if(ntmp2 >= 10000000) { result.data[i] = ntmp2 - 10000000; ntmp = 0; } else { result.data[i] = ntmp2; ntmp = -1; } } result.recalc(); return result; } } } this.multiply = function(num) /* 乘法 */ { var bpositive; var ndecimalplace = this.decimal_place + num.decimal_place - 1; if(this.positive == num.positive) { bpositive = true; } else { bpositive = false; } var result = new bignum("", 0, bpositive); var ntmpdata = 0; for( var i = 16; i >= 0; i -- ) { for( var j = 16; j >= 0; j -- ) { if(isnan(result.data[j + i])) result.data[j + i] = 0; result.data[j + i] += this.data[j] * num.data[i]; if(result.data[j + i] >= 10000000) { if( j + i -1 >= 0 ) { result.data[j + i -1] += math.floor(result.data[j + i] / 10000000); } else { ntmpdata += math.floor(result.data[j + i] / 10000000); } result.data[j + i] = result.data[j + i] % 10000000; } } } if(ntmpdata > 0) { result.data.unshift(ntmpdata); result.data.pop(); ndecimalplace ++; } result.decimal_place += ndecimalplace; return result; } this.divide = function(num) /* 除法 */ { var bpositive; var ndecimalplace = this.decimal_place - num.decimal_place + 1; if(this.positive == num.positive) { bpositive = true; } else { bpositive = false; } var result = new bignum("", 0, bpositive); var arrtemp = new array(17); for( var i = 0; i < 17; i ++ ) { arrtemp[i] = this.data[i]; } var btest = true; var ntest = 0; for( var i = 0; i < 17; i ++ ) { if(btest) { ntest = math.floor( ( arrtemp[0] * 10000000 + arrtemp[1] ) / ( num.data[0] * 10000000 + num.data[1] ) ); } else { btest = true; } if(ntest == 0) { result.data[i] = 0; arrtemp[1] += arrtemp[0] * 10000000; arrtemp.shift(); arrtemp.push(0); continue; } var arrtemp1 = new array(17); for( var j = 0; j < 17; j ++ ) { arrtemp1[j] = 0; } for( var j = 16; j >= 0; j -- ) { arrtemp1[j] += ntest * num.data[j]; if(arrtemp1[j] >= 10000000) { if(j != 0) { arrtemp1[j - 1] += math.floor( arrtemp1[j] / 10000000); arrtemp1[j] = arrtemp1[j] % 10000000; } } } for( var j = 0; j < 17; j ++ ) { if(arrtemp[j] < arrtemp1[j]) { btest = false; break; } else if(arrtemp[j] > arrtemp1[j]) { break; } } if(btest) { result.data[i] = ntest; for( var j = 16; j >= 0; j -- ) { if(arrtemp[j] >= arrtemp1[j]) { arrtemp[j] -= arrtemp1[j]; } else { arrtemp[j] = 10000000 + arrtemp[j] - arrtemp1[j]; arrtemp[j - 1] --; } } } else { ntest --; i --; continue; } arrtemp[1] += arrtemp[0] * 10000000; arrtemp.shift(); arrtemp.push(0); } result.decimal_place = ndecimalplace; result.recalc(); return result; } this.squareroot = function() /* 平方根 */ { var result = new bignum("", 0, true); ndecimalplace = math.ceil(this.decimal_place / 2); var arrtemp = new array(17); for(var i = 0; i < 17; i ++) { arrtemp[i] = this.data[i]; } var btest = true; for(var i = 0; i < 17; i ++) { if( i == 0 ) { if(this.decimal_place % 2 == 0) { var ntemp = arrtemp[0] * 10000000 + arrtemp[1]; var ntemp1 = math.floor( math.sqrt( ntemp ) ); var ntemp2 = ntemp - ntemp1 * ntemp1; arrtemp[0] = 0; arrtemp[1] = ntemp2; arrtemp.shift(); arrtemp.push(0); } else { var ntemp1 = math.floor( math.sqrt( arrtemp[0] ) ); var ntemp2 = arrtemp[0] - ntemp1 * ntemp1; arrtemp[0] = ntemp2; } } else { if(btest) { if( i == 1 ) { ntemp1 = math.sqrt( (arrtemp[0] * 10000000 + arrtemp[1]) + 100000000000000 * math.pow(result.data[0], 2) ) - 10000000 * result.data[0]; ntemp1 = math.floor(ntemp1); } else { ntemp = result.data[0] * 10000000 + result.data[1]; ntemp1 = math.floor( ( arrtemp[0] * 10000000 + arrtemp[1] ) / ( 2 * ntemp ) ); } } else { btest = true; } var arrtemp1 = new array(17); var ntemp3 = 0 for( var j = i - 1; j >= 0; j -- ) { arrtemp1[j] = result.data[j] * 2 + ntemp3; if( arrtemp1[j] >= 10000000 && j > 0 ) { ntemp3 = 1; arrtemp1[j] = arrtemp1[j] % 10000000; } else { ntemp3 = 0; } } arrtemp1[i] = ntemp1; ntemp3 = 0; for( var j = i; j >= 0; j -- ) { arrtemp1[j] = arrtemp1[j] * ntemp1 + ntemp3; if( arrtemp1[j] >= 10000000 && j > 0 ) { ntemp3 = math.floor( arrtemp1[j] / 10000000 ); arrtemp1[j] = arrtemp1[j] % 10000000; } else { ntemp3 = 0; } } var arrtemp2 = new array(17); for( var j = 0; j < 17; j ++ ) { arrtemp2[j] = arrtemp[j]; } for( var j = i; j >= 0; j -- ) { if( arrtemp2[j] >= arrtemp1[j] ) { arrtemp2[j] -= arrtemp1[j]; } else { if(j > 0) { arrtemp2[j] = arrtemp2[j] + 10000000 - arrtemp1[j]; arrtemp2[j - 1] --; } else { btest = false; break; } } } if(btest) { arrtemp = arrtemp2; } else { ntemp1 --; i --; continue; } } result.data[i] = ntemp1; arrtemp[1] += arrtemp[0] * 10000000; arrtemp.shift(); arrtemp.push(0); } result.decimal_place = ndecimalplace; result.recalc(); return result; } this.tostring = function() /* 转换为字符串(包括小数点),以便以文本形式输出计算结果 */ { var szdata = ""; var szoutput = ""; this.recalc(); for( var i = 0; i < 17; i ++ ) { var sztmpdata = this.data[i].tostring() var arr = new array(8 - sztmpdata.length); szdata += arr.join("0") + sztmpdata; } if( /^0*$/.test(szdata) ) { return "0"; } var n = this.decimal_place * 7; for(var i = 0; i < 7; i++) { if(szdata.substr(i, 1) != 0) break; n --; } szdata = szdata.replace(/^0+/g,""); szdata = szdata.substr(0, 101); szdata = szdata.replace(/0+$/g,""); if( n < 1 ) { szoutput = szdata.substr(0, 1) + ( ( szdata.length > 1 ) ? "." : "" ) + szdata.substr(1) + "e" + ( n - 1 ).tostring(); } else if(n == szdata.length) { szoutput = szdata; } else if(n > szdata.length) { szoutput = szdata.substr(0, 1) + "." + szdata.substr(1) + "e+" + (n - 1).tostring(); } else { szoutput = szdata.substr(0, n) + "." + szdata.substr(n); } return ( this.positive ? "" : "-" ) + szoutput; } this.clone = function() /* 复制 */ { var result = new bignum("", 0, true); for( var i = 0; i < 17; i ++) { result.data[i] = this.data[i]; } result.decimal_place = this.decimal_place; result.positive = this.positive; return result; } } var a = new bignum("1", 1, true) var count = 168; var ntwo = new bignum("2", 1, true); function loop(inttmpvar,intcount) { if(intcount == 0) return inttmpvar; var v1 = inttmpvar.divide( ntwo ); var v11 = v1.clone(); var ntemp = v1.multiply( v11 ); var a1 = a.clone(); a1 = a.multiply(a1); var ntemp1 = a1.subtract( ntemp ) v2 = ntemp1.squareroot(); v3 = a.subtract( v2 ); var v31 = v3.clone(); var ntemp2 = v3.multiply( v31 ); var ntemp3 = ntemp2.add(ntemp); v4 = ntemp3.squareroot(); return loop( v4 , -- intcount ) } var a1 = a.clone(); var ntemp = a.multiply(a1); var ntemp1 = ntemp.clone(); ntemp = ntemp.add(ntemp1); ntemp = loop(ntemp.squareroot(), count); var nfour = new bignum("4", 1, true); ntemp = ntemp.multiply( nfour ); ntemp1 = new bignum("2", 1, true); var ntemp2 = new bignum("2", 1, true); for(var i = 0; i < count - 1; i ++) { ntemp1 = ntemp1.multiply( ntemp2 ); } ntemp = ntemp.multiply( ntemp1 ); ntemp = ntemp.divide( ntwo ); ntemp = ntemp.divide( a ); document.write( ntemp ) //--> </script> </body> </html>
运行结果:
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
ps:这里再为大家推荐几款计算工具供大家进一步参考借鉴:
在线一元函数(方程)求解计算工具:
科学计算器在线使用_高级计算器在线计算:
在线计算器_标准计算器:
更多关于javascript相关内容感兴趣的读者可查看本站专题:《javascript数学运算用法总结》、《javascript数据结构与算法技巧总结》、《javascript数组操作技巧总结》、《javascript事件相关操作与技巧大全》、《javascript操作dom技巧总结》及《javascript字符与字符串操作技巧总结》
希望本文所述对大家javascript程序设计有所帮助。
上一篇: 浅谈vue项目如何打包扔向服务器