2011-12-03 38 views
8

Tôi muốn biết cách tôi có thể tạo pi cho chữ số thứ n. Tôi có một vài ý tưởng cơ bản.tạo chữ số pi đến số thứ j

  1. Sử dụng Math.PI và tăng độ chính xác (nếu có thể) công thức
  2. Sử dụng Euler để tạo pi nhưng ngay cả ở đây, tôi sẽ cần phải tăng độ chính xác (tôi nghĩ) Euler's formula for PI
  3. Ngoài ra còn có Srinivasa Công thức của Ramanujan để tạo ra PI được biết đến với sự hội tụ nhanh chóng. Công thức này có vẻ khó thực hiện. Tôi tin rằng, tôi cũng sẽ phải tăng độ chính xác deicmal ở đây.
    enter image description here

Vì vậy, trong ngắn hạn, một trong hai cách, tôi sẽ cần phải tăng độ chính xác của BigDecimal tùy thuộc vào những gì các chữ số thứ n là. Làm cách nào để tăng độ chính xác của BigDecimal thành chữ số thứ n? Ngoài ra, nếu có một tốt hơn và nhanh hơn làm điều này, bạn có thể xin vui lòng chỉ cho tôi đi đúng hướng.

EDIT: Tôi chỉ muốn tạo PI. Tôi không muốn sử dụng để tính toán. và đây là câu hỏi về cách tôi có thể sử dụng BigDecimal để triển khai ý tưởng tạo PI.

+0

Bạn có thực sự cần phải tạo ra Pi hay bạn cần nó để tính toán? –

+0

Đây có phải là câu hỏi về toán học đằng sau tính toán pi hay về cách sử dụng 'BigDecimal'? –

+0

Tôi chỉ sử dụng BigDecimal để triển khai các công thức PI và tôi không cần PI để tính toán, tôi chỉ muốn tạo nó. –

Trả lời

6
  • Math.PI thuộc loại double. Điều đó có nghĩa là khoảng 15 chữ số thập phân chính xác, và đó là tất cả dữ liệu bạn có; không có gì kỳ diệu sẽ tạo thêm các chữ số PI xuất hiện.
  • BigDecimal có độ chính xác tùy ý. setScale() cho phép bạn tạo các đối tượng BigDecimal với độ chính xác như bạn muốn và hầu hết các phương pháp số học sẽ tự động tăng độ chính xác theo yêu cầu, nhưng tất nhiên độ chính xác càng cao thì tất cả các phép tính sẽ càng chậm.
  • Phần khó nhất trong việc thực hiện công thức Ramanujan sẽ trớ trêu thay là sqrt (2) trong hệ số không đổi, vì không có sqrt() cho BigDecimal, vì vậy bạn sẽ phải tự viết.
+0

Nhưng đối với căn bậc hai, phương pháp Heron cũ tốt hội tụ đủ nhanh ngay cả với một triệu (hoặc một tỷ) chữ số chính xác. –

+0

cho phần sqrt (2), tôi có thể không chỉ sử dụng giá trị được xác định trước không? 1.41421356, hoặc sẽ thay đổi tính toán bằng cách nào đó? –

+0

@ user681159: tốt, ngay sau khi bạn muốn giá trị của PI chính xác hơn rằng "giá trị được xác định trước", bạn sẽ cần nhiều chữ số hơn của sqrt (2). –

3

Bạn cần phải sử dụng MathContext để tăng độ chính xác của BigDecimal

ví dụ

MathContext mc = new MathContext(1000); 
BigDecimal TWO = new BigDecimal(2, mc); 

Điều quan trọng là tất cả các BigDecimal s bạn sử dụng trong tính toán của bạn sử dụng MathContext. Phương pháp của Heron sẽ cung cấp cho bạn 1000 chữ số chính xác chỉ với 10 lần lặp và một triệu chữ số với 20 lần lặp lại vì vậy nó chắc chắn đủ tốt. Ngoài ra, hãy tạo tất cả các hằng số BigDecimal s như ví dụ: 26390 chỉ một lần khi bắt đầu chương trình của bạn.

+0

Ý của bạn là gì theo phương pháp của Heron? –

+0

@ user681159 Phương pháp của Heron trùng với phương pháp Newton-Raphson đối với trường hợp căn bậc hai, trong trường hợp bạn quen thuộc với phương pháp sau. Ngược lại: nó tìm kiếm xấp xỉ tốt hơn với 'sqrt (a)' thông qua 'x_ (n + 1) = 1/2 * (x_n + a/x_n)'. Nó hội tụ cho tất cả 'a> 0' và bất kỳ giá trị bắt đầu' x_0> 0' nào. Nếu bạn bắt đầu với một xấp xỉ khá tốt, trong mỗi bước số chữ số chính xác tăng gấp đôi (khoảng). –

0

Bạn có thể sử dụng mã này

import java.math.BigDecimal; 
import java.math.RoundingMode; 

public final class Pi { 

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 TWO_THIRTY_NINE = new BigDecimal("239"); 

private Pi() {} 

public static BigDecimal pi(int numDigits) { 

    int calcDigits = numDigits + 10; 

    return FOUR.multiply((FOUR.multiply(arccot(FIVE, calcDigits))) 
    .subtract(arccot(TWO_THIRTY_NINE, calcDigits))) 
    .setScale(numDigits, RoundingMode.DOWN); 
} 

private static BigDecimal arccot(BigDecimal x, int numDigits) { 

BigDecimal unity = BigDecimal.ONE.setScale(numDigits, 
    RoundingMode.DOWN); 
BigDecimal sum = unity.divide(x, RoundingMode.DOWN); 
BigDecimal xpower = new BigDecimal(sum.toString()); 
BigDecimal term = null; 

boolean add = false; 

for (BigDecimal n = new BigDecimal("3"); term == null || 
    term.compareTo(BigDecimal.ZERO) != 0; n = n.add(TWO)) { 

    xpower = xpower.divide(x.pow(2), RoundingMode.DOWN); 
    term = xpower.divide(n, RoundingMode.DOWN); 
    sum = add ? sum.add(term) : sum.subtract(term); 
    add = ! add; 
} 
return sum; 
} 
} 

resource

+0

Có một vấn đề với mã này nó dẫn đến một vòng lặp vô hạn trong điều kiện nhất định ;-( –

Các vấn đề liên quan