2010-11-05 18 views
5

Piszę funkcję, która oblicza wartość PI i zwraca ją jako podwójne. Jak na razie dobrze. Ale gdy funkcja osiągnie 14 cyfr po przecinku, nie może już dłużej wytrzymać. Zakładam, że jest tak z powodu ograniczonej precyzji podwójnej. Co mam zrobić, aby nadal otrzymywać więcej cyfr po przecinku?C# Wysoka podwójna precyzja

Odpowiedz

16

Nie zrobiłbym tego w ogóle.

Przypomnijmy, że algorytm jest:

(1 + 1/(2 * 1 + 1)) * 
(1 + 2/(2 * 2 + 1)) * 
(1 + 3/(2 * 3 + 1)) * 
(1 + 4/(2 * 4 + 1)) * 
(1 + 5/(2 * 5 + 1)) * 
(1 + 6/(2 * 6 + 1)) * 
(1 + 7/(2 * 7 + 1)) * ... 

Każdy etap na drodze obliczyć ułamek. Dlaczego po prostu nie zatrzymasz tej frakcji w jej liczniku/mianowniku? Frakcja chcesz obliczyć to:

(4/3) * 
(7/5) * 
(10/7) * 
(13/9) * ... 

który jest tylko 4 * 7 * 10 * 13 ... na górze i 3 * 5 * 7 * 9 na dnie.

Zdobądź klasę BigInteger (dostarczaną z ramą 4.0 w System.Numerics) i możesz łatwo obliczyć licznik i mianownik tak duży, jak chcesz. Wtedy masz problem z konwersją ilorazu na dziesiętny. To dość łatwe. Prawdopodobnie wiesz, jak zrobić długi podział. Wystarczy zaimplementować algorytm długiego podziału na liczniku i mianowniku, który wypisze pożądaną liczbę cyfr.

8

Jaką dokładność potrzebujesz?

Korzystanie decimal daje około 28 miejsc po przecinku:

decimal pi = 3.14159265358979323846264338327950288419716939937510m; 
Console.WriteLine(pi); // 3.1415926535897932384626433833 

Jeśli to nie wystarczy, wtedy trzeba szukać jakiegoś realizacji BigDecimal, czy patrzeć na innych technik wykonywania obliczeń .

0

Tak, ponieważ ograniczona jest precyzja podwójna. Istnieje kilka różnych sposobów obliczania cyfr pi. Sugerowałbym zapytanie do ulubionej wyszukiwarki "jak obliczyć cyfry pi".

1

Istnieje kilka bibliotek, które umożliwiają pracę z dowolną precyzją. Jedna to W3b.sine, ale kilka innych opisano na stronie wikipedia.

1

Wypróbuj decimal zamiast podwójnie. Nie może przechowywać liczb tak dużych jak podwójne, ale myślę, że ma większą precyzję po przecinku. Jeśli potrzebujesz więcej, prawdopodobnie będziesz musiał użyć ciągu.

+0

Nie użyłbym napisu - miałbyś dodatkowy nakład na konwersję do/z liczb. – JLWarlow

+0

Tak, ale jeśli potrzebujesz więcej niż er, 28-cyfrową precyzję, nie ma wbudowanych typów danych. IIRC C# ma jakąś klasę dla wartości z (prawie) nieograniczonym rozmiarem i jestem prawie pewien, że zapisałby je wewnętrznie jako ciąg ... – user472875

+0

... lub tablicę bajtów. –