2012-08-28 9 views
5

Typ danych podwójnych nie może poprawnie reprezentować niektórych wartości podstawowych 10. Wynika to z tego, jak liczby zmiennoprzecinkowe reprezentują liczby rzeczywiste. Oznacza to, że przy reprezentowaniu wartości pieniężnych należy używać typu wartości dziesiętnej, aby zapobiec błędom. (prosimy o poprawianie błędów w tej preambule)Które wartości nie mogą być poprawnie odwzorowane przez podwójny

Co chcę wiedzieć, jakie są wartości, które przedstawiają taki problem pod podwójnym typem danych w 64-bitowej architekturze w standardowym środowisku .Net (C#, jeśli to robi różnicę) ?

Spodziewam się, że odpowiedź będzie formułą lub regułą, aby znaleźć takie wartości, ale chciałbym również kilka przykładowych wartości.

+0

Użyj wartości dziesiętnej, gdy reprezentujesz wartości pieniężne - to jest prawda .. i należy ich przestrzegać, zarówno na 64-bitowym, jak i 32-bitowym łuku. – JonH

+0

Lub centów (lub subcents) jako BigInteger :) – Joey

+0

Jeśli chodzi o określenie .Net, 64 architektury, itp. Było w przypadku były jakieś szczegóły realizacji, które musiały być brane pod uwagę, aby odpowiedzieć na moje pytanie. – Gilles

Odpowiedz

7

Dowolna liczba, która nie może być zapisana jako suma dodatnich i ujemnych potęg 2 nie można dokładnie przedstawić jako binarnej liczby zmiennoprzecinkowej.

Wspólne IEEE formats for 32- i 64-bitowe reprezentacje liczb zmiennoprzecinkowych nakładają dodatkowe ograniczenia; ograniczają liczbę cyfr binarnych zarówno w meanand, jak i wykładniku. Istnieją więc liczby reprezentatywne (maksimum i minimum) (w przybliżeniu +/- 10^308 (base-10), jeśli pamięć służy) i ograniczenia precyzji liczby, która może być reprezentowana. Ten limit precyzji oznacza, że ​​dla liczb 64-bitowych różnica między wykładnikiem o największej potędze 2 i najmniejszą mocą w liczbie jest ograniczona do 52, więc jeśli twoja liczba zawiera termin w 2^52, to może 't również zawierają termin w 2^-1.

Proste przykłady liczb, których nie można dokładnie odwzorować w liczbach zmiennoprzecinkowych, to:

Ponieważ zbiór liczb zmiennoprzecinkowych (w dowolnej reprezentacji) jest skończony, a zbiór liczb rzeczywistych jest nieskończony, jednym z algorytmów do znalezienia liczby rzeczywistej, która nie jest dokładnie reprezentowana jako liczba zmiennoprzecinkowa, jest wybranie prawdziwa liczba losowo. Prawdopodobieństwo, że prawdziwa liczba jest dokładnie reprezentowana jako liczba zmiennoprzecinkowa, to 0.

+1

Podczas gdy '10^5000' nie może być reprezentowany przez' podwójne', może być dokładnie odwzorowane jako binarna liczba zmiennoprzecinkowa. – CodesInChaos

1

To pytanie wykracza poza dowolny język programowania lub platformę. Niedokładność jest rzeczywiście nieodłączna w danych binarnych.

Należy wziąć pod uwagę, że z podwójnym, każda liczba N po lewej stronie (w indeksie 0 w punkcie zerowym) kropki dziesiętnej reprezentuje wartość N * 2^I, a każda cyfra po prawej stronie przecinka dziesiętnego reprezentuje wartość N * 2^(- I).

Jako przykład, 5,625 (podstawa 10) będzie 101,101 (podstawa 2).

Biorąc pod uwagę to obliczenie i wartość dziesiętną, która nie może być obliczona jako suma 2^(- I) dla różnych wartości, miałbym niepoprawną wartość jako podwójną.

+1

To tylko nasuwa pytanie. Skąd mam wiedzieć, czy konkretna dziesiętna wartość podstawowa 10 może być reprezentowana jako N * 2^-i dla skończonej i? – Servy

+0

@Servy: http://cs.furman.edu/digitaldomain/more/ch6/dec_frac_to_bin.htm i wiele innych referencji odpowiadają na twoje pytanie. –

+1

@HighPerformanceMark Powinieneś to uwzględnić w swojej odpowiedzi. Bez tego właściwie nie pomagasz mu rozwiązać problemu, tylko dajesz mu nowy problem do rozwiązania. – Servy

1

Powinieneś być przygotowany na to, że każda wartość przechowywana w numerze double zawiera niewielki błąd. O ile nie przechowujesz stałej wartości, jest szansa, że ​​może to być coś z co najmniej pewnym błędem. Jeśli konieczne jest, aby nigdy nie wystąpił błąd, a wartości nie są stałe, prawdopodobnie nie powinno się używać typu zmiennoprzecinkowego.

W wielu przypadkach powinieneś zadać pytanie: "Jak sobie poradzić z drobnymi błędami zmiennoprzecinkowymi?" Będziesz chciał wiedzieć, jakie typy operacji mogą powodować wiele błędów, a jakie typy nie. Będziesz chciał upewnić się, że porównanie dwóch wartości "równości" faktycznie zapewnia, że ​​są one "wystarczająco blisko", a nie dokładnie równe, itp.

+0

Dlaczego zostało to odrzucone - nie ma w tym nic z natury błędnego? – JonH

+0

@JonH Sam jestem trochę ciekawy. Sądzę, że technicznie nie odpowiedziałem na to pytanie, próbowałem rozwiązać problem root bez względu na zadawane pytanie. – Servy

+0

Ale twoja odpowiedź pomoże ci odpowiedzieć na pytanie, ja to zrobię, ale obawiam się, że to jakiś rodzaj odwetu, nie ma nic złego w twoim oświadczeniu. – JonH

1

Pływak jest reprezentowane s, e i m następującym wzorem

s * m * 2^e 

Oznacza to, że liczba ta nie może być reprezentowany za pomocą danego wyrażenia (i odpowiednimi domenami s, e i m) nie można dokładnie przedstawić.

Zasadniczo można reprezentować wszystkie liczby między 0 i 2^53 - 1 pomnożone przez pewną potęgę dwóch (prawdopodobnie ujemną).

Na przykład, wszystkie liczby między 0 i 2^53 - 1 można przedstawić mnożona 2^0 = 1. Można również reprezentować wszystkie te liczby, dzieląc je przez 2 (z frakcją .5). I tak dalej.

Ta odpowiedź nie w pełni obejmuje temat, ale mam nadzieję, że pomoże.

Powiązane problemy