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
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.
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ń .
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".
Można użyć typu J # BigDecimal
, jak zasugerowano w this answer.
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.
Nie użyłbym napisu - miałbyś dodatkowy nakład na konwersję do/z liczb. – JLWarlow
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
... lub tablicę bajtów. –