JavaScript实现计算圆周率到小数点后100位的方法示例


Posted in Javascript onMay 08, 2018

本文实例讲述了JavaScript实现计算圆周率到小数点后100位的方法。分享给大家供大家参考,具体如下:

浮点数的有效数位是16位,我自己做了一个大数类,能存储100位有效数位,并实现了大数类的基本运算。我用它来计算圆周率(割圆法,即多边形逼近),得到了小数点后一百位有效数字,比对了Machin 公式的计算结果,没有误差。用时约2秒。

完整示例如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>3water.com 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:这里再为大家推荐几款计算工具供大家进一步参考借鉴:

在线一元函数(方程)求解计算工具:
http://tools.3water.com/jisuanqi/equ_jisuanqi

科学计算器在线使用_高级计算器在线计算:
http://tools.3water.com/jisuanqi/jsqkexue

在线计算器_标准计算器:
http://tools.3water.com/jisuanqi/jsq

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
jQuery.getScript加载同域JS的代码
Feb 13 Javascript
简单的代码实现jquery定时器
Nov 17 Javascript
JavaScript函数定义的常见注意事项小结
Sep 16 Javascript
jquery实现多条件筛选特效代码分享
Aug 28 Javascript
基于JQuery实现仿网易邮箱全屏动感滚动插件fullPage
Sep 20 Javascript
jQuery EasyUI提交表单验证
Jul 19 Javascript
el表达式 写入bootstrap表格数据页面的实例代码
Jan 11 Javascript
Vue 2.X的状态管理vuex记录详解
Mar 23 Javascript
基于angular实现模拟微信小程序swiper组件
Jun 11 Javascript
vue2组件之select2调用的示例代码
Oct 12 Javascript
Vue源码解析之Template转化为AST的实现方法
Dec 14 Javascript
vue 使用rules对表单字段进行校验的步骤
Dec 25 Vue.js
Vue.js 实现微信公众号菜单编辑器功能(二)
May 08 #Javascript
详解基于mpvue的小程序markdown适配解决方案
May 08 #Javascript
Vue.js 实现微信公众号菜单编辑器功能(一)
May 08 #Javascript
浅谈React 服务器端渲染的使用
May 08 #Javascript
vue.js做一个简单的编辑菜谱功能
May 08 #Javascript
webstorm和.vue中es6语法报错的解决方法
May 08 #Javascript
vue2.0实现移动端的输入框实时检索更新列表功能
May 08 #Javascript
You might like
php select,radio和checkbox默认选择的实现方法
2010/05/15 PHP
利用curl抓取远程页面内容的示例代码
2013/07/23 PHP
PHP之uniqid()函数用法
2014/11/03 PHP
Symfony2开发之控制器用法实例分析
2016/02/05 PHP
phpstudy2018升级MySQL5.5为5.7教程(图文)
2018/10/24 PHP
jQuery+PHP实现图片上传并提交功能
2020/07/27 PHP
instanceof和typeof运算符的区别详解
2014/01/06 Javascript
js写的方法实现上传图片之后查看大图
2014/03/05 Javascript
jQuery判断复选框是否勾选的原理及示例
2014/05/21 Javascript
JavaScript设计模式之抽象工厂模式介绍
2014/12/28 Javascript
基于bootstrap插件实现autocomplete自动完成表单
2016/05/07 Javascript
JavaScript中数组的各种操作的总结(必看篇)
2017/02/13 Javascript
使用ng-packagr打包Angular的方法示例
2018/09/21 Javascript
移动端(微信等使用vConsole调试console的方法
2019/03/05 Javascript
简单了解vue中的v-if和v-show的区别
2019/10/08 Javascript
Node.js 实现抢票小工具 &amp; 短信通知提醒功能
2019/10/22 Javascript
JS实现简易留言板(节点操作)
2020/03/16 Javascript
[01:09]DOTA2次级职业联赛 - 99战队宣传片
2014/12/01 DOTA
Python设计模式之代理模式实例
2014/04/26 Python
Python聊天室实例程序分享
2016/01/05 Python
解决Jupyter notebook更换主题工具栏被隐藏及添加目录生成插件问题
2020/04/20 Python
详解python变量与数据类型
2020/08/25 Python
Pycharm如何自动生成头文件注释
2020/11/14 Python
利用Python实现自动扫雷小脚本
2020/12/17 Python
基于Pytorch版yolov5的滑块验证码破解思路详解
2021/02/25 Python
python和opencv构建运动检测器的实现
2021/03/03 Python
基于HTML5+Webkit实现树叶飘落动画
2017/12/28 HTML / CSS
prAna官网:瑜伽、旅行和冒险服装
2019/03/10 全球购物
意大利奢侈品多品牌集合店:TheDoubleF
2019/08/24 全球购物
The Athlete’s Foot新西兰:新西兰最大的运动鞋零售商
2019/12/23 全球购物
总经理文秘岗位职责
2014/02/03 职场文书
大学感恩节活动策划方案
2014/10/11 职场文书
逃课检讨书怎么写
2015/01/01 职场文书
MySQL之PXC集群搭建的方法步骤
2021/05/25 MySQL
用python批量解压带密码的压缩包
2021/05/31 Python
UNION CREATIVE《Re:从零开始的异世界生活》雷姆手办
2022/03/20 日漫