如何使用BBP公式直接計算π的第n位
使用BBP公式可以直接求得十六進位制π的第n位而不需要計算前n位的數,以下公式將直接求出十進位制的π:
其中引數
k
代表的是所求π的精度,例如:當您希望求出π的前13位的話您只需要將k替換成13即可。其計算出來的結果為3.1415926...
接下來是如何求得十六進位制π的第n位。
首先,您需要知道一個知識點:十進位制的小數如何轉換為十六進位制?
例如,小數3.1415926
轉換為16進製為3.243f69a25b094
,為了獲取第一個16進位制的小數,我們只需要取3.1415926
的小數部分0.1415925
乘以16
即可得到2.2654816
,結果的整數位數即為16十六進位制小數轉換後端結果,再取2.2654816
0.2654816
乘以16
即可得到第二個16進位制小數位,依次類推,當整數部分位10、11、12等大於9的數時,使用a、b、c等代替即可。
所以,如果需要得到16進位制π的第n個數,只需要求得16^n*π即可: 其中
計算時,將式子中的
j
替換為1、4、5、6然後分別代入上式即可。 式子中的k
表示精度,d
表示需要計算π的哪一位置
繼續得到
這裡有兩點值得注意:
- 式子中的
mod
符號意為求模,即取16^(d-k)除以(8k+j)得餘數,然後再除以(8k+j),這樣做的目的是:在計算過程中就去除整數部分(因為我們只需要的是小數部分,整數部分可以直接去除,這在當資料變得非常大時可以極大提高計算效率)。- 將求和部分拆分為兩部分[0,d,正無窮]原因和第一點一樣,這樣的話後面的式子就一定是個小數。所以,真正在計算過程中一定要保證
k>d
。 然後將計算結果代入第一個式子中即可
最後,還需要注意的點是:代入之後求得的結果需要先去除整數部分然後再乘以16即可得到16進位制π的第n位。並且,為了保證第一個式子中求出來的值不為負值,您可能需要在做第一個減法之前加上一個大於4的整數。
下面貼出java程式碼: 您需要首先在類中新增常量
private static final BigDecimal ONE = BigDecimal.ONE;
private static final BigDecimal TWO = new BigDecimal(2);
private static final BigDecimal FOUR = new BigDecimal(4);
private static final BigDecimal FIVE = new BigDecimal(5);
private static final BigDecimal SIX = new BigDecimal(6);
private static final BigDecimal EIGHT = new BigDecimal(8);
private static final BigDecimal SIXTEEN = new BigDecimal(16);
以下為方法實現程式碼,其中calc16dPI
即表示計算(16^d)*π
,calc16dSj
即表示計算(16^d)*Sj
,可以看到,我將k(即程式碼中的ACCURACY)
設定為了d+10
,這個數是我隨便設定的,你也可以將其設定成其他的,具體影響大不大我還沒研究。
BigDecimal calc16dPI(int d) {
return FOUR.multiply(calc16dSj(d, 1)).add(BigDecimal.valueOf(3)).subtract(TWO.multiply(calc16dSj(d, 4)).divideAndRemainder(ONE)[1]).subtract(calc16dSj(d, 5).divideAndRemainder(ONE)[1]).subtract(calc16dSj(d, 6).divideAndRemainder(ONE)[1]).divideAndRemainder(ONE)[1];
}
BigDecimal calc16dSj(int d, int j) {
int ACCURACY = d + 10;
BigDecimal part1 = BigDecimal.ZERO;
BigDecimal part2 = BigDecimal.ZERO;
for (int k = 0; k <= d; k++) {
part1 = part1.add(SIXTEEN.pow(d - k).divideAndRemainder(EIGHT.multiply(BigDecimal.valueOf(k)).add(BigDecimal.valueOf(j)))[1].divide(EIGHT.multiply(BigDecimal.valueOf(k)).add(BigDecimal.valueOf(j)), ACCURACY, BigDecimal.ROUND_HALF_UP));
}
for (int k = d + 1; k < ACCURACY; k++) {
part2 = part2.add(ONE.divide(SIXTEEN.pow(k - d).multiply(EIGHT.multiply(BigDecimal.valueOf(k)).add(BigDecimal.valueOf(j))), ACCURACY, BigDecimal.ROUND_HALF_UP));
}
return part1.add(part2);
}
以下為測試方法,計算十六進位制π的前100位,注意在結果上乘以一個16
:
@Test
public void mainCalc() {
for (int d = 0; d < 100; d++) {
System.out.println("index of " + (d + 1) + ": " + calc16dPI(d).multiply(SIXTEEN));
}
}
執行結果截圖:
分別得到
2、4、3、15、6、10、8、8、8、5...
則π的十六進位制數應該為3.243f6a8885a3