梅欽公式

梅欽公式是一個至今仍被廣泛套用的計算 π 值的公式。

基本介紹

  • 中文名:梅欽公式
  • 外文名:Machin formula
簡介,實現,

簡介

1706年,英國人 約翰·梅欽( John Machin) 發明了一個用於計算
值的公式:
或者寫為:
梅欽公式是格里高利/萊布尼茨計算
的公式的變體,但是更實用,它的收斂速度顯著增加,這使得它成為了更實用的計算
的方法,雖然有若干種類梅欽(Machin-like)公式,但梅欽公式至今仍然是計算
值的主要公式。

實現

這裡給出一種 JavaScript 實現,如下:
/** @Author: suifengtec* @Date:   2017-08-22 05:40:48* @Last Modified by:   suifengtec* @Last Modified time: 2017-08-23 03:18:37**//*用JavaScript 和 梅欽公式計算 PI。使用node pi.js */var getPi = (function () {    function getPi(space) {        this.aX = [];        this.cellSize = 11;           this.tStart = new Date();        this.spaceStr = space ? space : "  ";        this.aBigInt = Math.pow(10, this.cellSize);    }    getPi.prototype.getIt = function (length) {        var digitsLenAfterDot = Number(length);        var cellSize = this.cellSize;        var coeff = Array(10),         iAng = Array(10);        var arrLen = Math.ceil(1 + digitsLenAfterDot / cellSize);        var aPI = Array(arrLen);        var aArctan = Array(arrLen);        coeff[0] = 4;        coeff[1] = -1;        coeff[2] = 0;        iAng[0] = 5;        iAng[1] = 239;        iAng[2] = 0;        aPI = this.makeArr(arrLen, aPI, 0);        for (var i = 0; coeff[i] != 0; i++) {            aArctan = this.getArcTan(iAng[i], arrLen, aArctan);            aArctan = this.Mul(arrLen, aArctan, Math.abs(coeff[i]));            if (coeff[i] > 0) {                aPI = this.Add(arrLen, aPI, aArctan);            }            else {                aPI = this.Sub(arrLen, aPI, aArctan);            }        }        aPI = this.Mul(arrLen, aPI, 4);        var sPI = "3.";          var tempPI = "";        for (var i = 0; i < aPI.length; i++) {            aPI[i] = String(aPI[i]);            if (aPI[i].length < cellSize && i != 0) {                while (aPI[i].length < cellSize) {                    aPI[i] = "0" + aPI[i];                }            }            tempPI += aPI[i];        }        for (var i = 0; i + 1 <= digitsLenAfterDot; i++) {            if (i == 0) {                sPI += tempPI.charAt(i + 1);            }            else {                var newLineSymbol = this.spaceStr, spForPer5Digits = this.spaceStr;                if ((i + 1) % 50 == 0 && i != 0) {                    sPI += tempPI.charAt(i + 1) + newLineSymbol;                }                else {                    if ((i + 1) % 5 == 0) {                        sPI += tempPI.charAt(i + 1) + spForPer5Digits;                    }                    else {                        sPI += tempPI.charAt(i + 1);                    }                }            }        }        var tShutdown = new Date();        var timeTaken = (tShutdown.getTime() - this.tStart.getTime()) / 1000;        var timeSp = "耗時: " + timeTaken + " 秒";        return sPI + " \n" + timeSp;    };    getPi.prototype.Mul = function (n, aX, iMult) {        var carry = 0;        var prod;        for (var i = n - 1; i >= 0; i--) {            prod = (aX[i]) * iMult;            prod += carry;            if (prod >= this.aBigInt) {                carry = Math.floor(prod / this.aBigInt);                prod -= (carry * this.aBigInt);            }            else {                carry = 0;            }            aX[i] = prod;        }        return aX;    };    getPi.prototype.Div = function (n, aX, iDiv, aY) {        var carry = 0;        var currVal;        var theDiv;        for (var i = 0; i < n; i++) {            currVal = Number(aX[i]) + Number(carry * this.aBigInt);            theDiv = Math.floor(currVal / iDiv);            carry = currVal - theDiv * iDiv;            aY[i] = theDiv;        }        return aY;    };    getPi.prototype.Add = function (n, aX, aY) {        var carry = 0;        for (var i = n - 1; i >= 0; i--) {            aX[i] += Number(aY[i]) + Number(carry);            if (aX[i] < this.aBigInt) {                carry = 0;            }            else {                carry = 1;                aX[i] = Number(aX[i]) - Number(this.aBigInt);            }        }        return aX;    };    getPi.prototype.Sub = function (n, aX, aY) {        for (var i = n - 1; i >= 0; i--) {            aX[i] -= aY[i];            if (aX[i] < 0) {                if (i > 0) {                    aX[i] += this.aBigInt;                    aX[i - 1]--;                }            }        }        return aX;    };    getPi.prototype.isEmpty = function (aX) {        var empty = true;        for (var i = 0; i < aX.length; i++) {            if (aX[i]) {                empty = false;                break;            }        }        return empty;    };    getPi.prototype.getArcTan = function (iAng, n, aX) {        var iAng_squared = iAng * iAng;        var k = 3;        var sign = 0;        var arrAngle = [];        var aDivK = [];        aX = this.makeArr(n, aX, 0);         arrAngle = this.makeArr(n, arrAngle, 1);        arrAngle = this.Div(n, arrAngle, iAng, arrAngle);        aX = this.Add(n, aX, arrAngle);        while (!this.isEmpty(arrAngle)) {            arrAngle = this.Div(n, arrAngle, iAng_squared, arrAngle);                       aDivK = this.Div(n, arrAngle, k, aDivK);             if (sign) {                aX = this.Add(n, aX, aDivK);             }            else {                aX = this.Sub(n, aX, aDivK);            }            k += 2;            sign = 1 - sign;        }        return aX;    };    getPi.prototype.makeArr = function (n1, arr, n2) {        for (var i = 0; i < n1; i++) {            arr[i] = null;        }        arr[0] = n2;        return arr;    };    return getPi;}());/*tsc pi.ts && node pi.js驗證3.14159 26535 89793 23846 26433 83279 50288 41971 69399 37510 58209 74944 59230 78164 06286 20899 86280 34825 34211 70679計算所得(小數點後100位)3.14159 26535 89793 23846 26433 83279 50288 41971 69399 37510 58209 74944 59230 78164 06286 20899 86280 34825 34211 70679耗時: 0.001 秒 */var spaceSymbol = "  ";var app = new getPi(spaceSymbol);var pi = app.getIt(100);console.log(pi);
上述實現一般情況下計算出來的精確度大於 JavaSript 的浮點數允許的精確值, 所以僅能以字元串形式輸出,不能參與運算。

相關詞條

熱門詞條

聯絡我們