Czy istnieją liczby, które nie są reprezentowalne w bazie 10, ale mogą być reprezentowane w bazie 2?

42

C#ma decimaltyp używany dla liczb, które wymagają dokładnej reprezentacji w bazie 10. Na przykład, 0.1nie może być reprezentowany w bazie 2 (np. floati double) i zawsze będzie przybliżeniem, gdy jest przechowywany w zmiennych tego typu.

Zastanawiałem się, czy odwrócony fakt był również możliwy. Czy istnieją liczby, które nie są reprezentowalne w bazie 10, ale mogą być reprezentowane w bazie 2 (w którym to przypadku chciałbym użyć floatzamiast decimalnich do obsługi)?

Max
źródło
14
+1 do pytania, ale czy tag c # naprawdę ma tutaj zastosowanie? Inne języki mają również typ dziesiętny.
Patrick M
1
@Max: W ramach ćwiczenia sugeruję, aby wyobrazić sobie ręczne przekształcanie liczby podstawowej 2 na bazę 10. Np. Aby obliczyć wartość 0.11_b2, zapisz ją jako 0.5 + 0.5 * 0.5. Czy istnieje krok, który może się nie powieść lub spowodować powtarzanie dziesiętne? Osobiście uważam, że ćwiczenie to wykonuje świetną robotę, jeśli chodzi o intuicję dotyczącą liczb podstawowych 2. Podejrzewam, że można pójść o krok dalej i zamienić to ćwiczenie w dowód budowlany.
Brian
Ach, ale się mylisz. 1/1010
Xavier J
3
@Ramhound Biorąc pod uwagę ograniczenia pamięci, plik binarny może reprezentować 0.0999999....998..dokładnie, ale nie pełną liczbę 0.1- przybliżenia, takie jak zaokrąglanie do najbliższej setki, 0.100stanowią problem z implementacją, który polega na tym, aby nie pokazywać wszystkich cyfr i zaokrąglać je.
Izkata,
1
Cóż, możliwe jest opracowanie mechanizmu kodowania FP, który pozwala na dokładne odwzorowanie „0,1”. Takie kodowanie jedynie przesuwa się wokół zestawów zakresów liczb FP, niż można i nie może być reprezentowane.
Martin James

Odpowiedzi:

104

Oto klucz do twojego rozterki: 10jest produktem 2i 5. Można reprezentować dowolną liczbę dokładnie w bazie 10 dziesiętne to k * 1/2 n * 1/5 m , gdzie k, ni msą liczbami całkowitymi.

Alternatywnie - jeśli liczba nw 1 / n zawiera czynnik, który nie jest częścią czynników podstawy, liczby nie będzie można przedstawić dokładnie w stałej liczbie cyfr w systemie binarnym / dziesiętnym / jakimkolwiek rozszerzeniu tego liczba - będzie miała część powtarzalną. Na przykład 1/15 = 0,0666666666 .... ponieważ 3 (15 = 3 * 5) nie jest współczynnikiem 10.

Zatem wszystko, co można dokładnie przedstawić w podstawie 2 (k * 1/2 n ), może być dokładnie przedstawione w podstawie 10.

Poza tym istnieje kwestia liczby cyfr / bitów używanych do przedstawienia liczby. Istnieje kilka liczb, które można dokładnie przedstawić w jakiejś bazie, ale zajmuje to więcej niż pewną liczbę cyfr / bitów.


W systemie dwójkowym liczba 1/10, która dogodnie wynosi 0,1 w systemie dziesiętnym, nie może być reprezentowana jako liczba, która może być reprezentowana przez stałą liczbę bitów w systemie dwójkowym. Zamiast tego jest to 0,00011001100110011 ... 2 (z częścią 0011 powtarzającą się na zawsze).

Spójrzmy na numer 1 2 /1010 2 nieco bliżej.

          ____                  
       0,00011                  
     + ---------                 
1010 | 1,00000                  
       0                        
       -                       
       1 0                      
         0                      
       ----                     
       1 00 --------- +          
          0 |          
       ----- |          
       1 000 |          
           0 |          
       ------ | powtórzenie
       1 0000 | blok    
         1010 |          
       ------ |          
          1100 |          
          1010 |          
          ---- |          
            100 ---- +          

Jest to dokładnie ten sam rodzaj rzeczy, który dostajesz, gdy próbujesz wykonać długi podział na 1/3.

1/10, gdy uwzględniono 1 / (2 1 * 5 1 ). W przypadku podstawy 10 (lub dowolnej wielokrotności 10) liczba ta kończy się i jest znana jako liczba zwykła . Rozwinięcie dziesiętne, które się powtarza, znane jest jako powtarzanie dziesiętne , a liczby, które trwają wiecznie bez powtarzania, są liczbami niewymiernymi.

Matematyki za tego zagłębia się małe twierdzenie Fermata ... i po uruchomieniu mówiąc Fermat lub twierdzenie, staje się pytanie Math.SE .

Czy istnieją liczby, które nie są reprezentowalne w bazie 10, ale mogą być reprezentowane w bazie 2?

Odpowiedź brzmi nie'.

Zatem w tym miejscu wszyscy powinniśmy wyjaśnić, że każde rozwinięcie binarne o stałej długości liczby wymiernej może być reprezentowane jako rozwinięcie dziesiętne o stałej długości.


Pozwala zapoznać się bliżej po przecinku w C # , który prowadzi nas do dziesiętny zmiennoprzecinkowych w .NET i danego autora, to zgadzam się, że to jak to działa.

Typ dziesiętny ma takie same składniki, jak każda inna liczba zmiennoprzecinkowa: mantysa, wykładnik potęgowy i znak. Jak zwykle znak jest tylko jednym bitem, ale jest 96 bitów mantysy i 5 bitów wykładnika potęgi. Jednak nie wszystkie kombinacje wykładników są prawidłowe. Działają tylko wartości 0–28 i wszystkie są faktycznie ujemne: wartością liczbową jest . Oznacza to, że maksymalne i minimalne wartości tego typu wynoszą +/- (2 96 -1), a najmniejsza liczba niezerowa pod względem wielkości bezwzględnej wynosi 10-28 .sign * mantissa / 10exponent

Od razu zaznaczę, że z powodu tej implementacji istnieją liczby w doubletypie, w których nie można reprezentować decimal- te, które są poza zakresem. Double.Epsilonjest to, 4.94065645841247e-324co nie może być reprezentowane w decimal, ale może w double.

Jednak w zakresie, który może reprezentować dziesiętny, ma więcej bitów dokładności niż w przypadku innych rodzimych typów i może reprezentować je bez błędów.

Istnieje kilka innych typów. W języku C # istnieje BigInteger, która może reprezentować dowolnie dużą liczbę całkowitą. Nie ma odpowiednik Java BigDecimal (który może reprezentować liczby z cyfr dziesiętnych do wysokości 2 32 cyfr - co jest sporym zasięgu) dokładnie . Jeśli jednak trochę się przekręcisz, możesz znaleźć ręcznie wdrażane implementacje.

Istnieje kilka języków, które mają również racjonalny typ danych, który pozwala dokładnie reprezentować racjonalne (tak, że 1/3 to w rzeczywistości 1/3).


Specjalnie dla C # i wyboru liczby zmiennoprzecinkowej lub wymiernej, odłożę się do Jona Skeeta z pływającego kufla dziesiętnego w .NET :

Większość aplikacji biznesowych prawdopodobnie powinna używać liczb dziesiętnych zamiast liczb zmiennoprzecinkowych lub podwójnych. Moja ogólna zasada jest taka, że ​​wartości stworzone przez człowieka, takie jak waluta, są zwykle lepiej reprezentowane przez zmiennoprzecinkowe dziesiętne: na przykład koncepcja dokładnie 1,25 dolara jest całkowicie rozsądna. W przypadku wartości ze świata przyrody, takich jak długości i masy, binarne typy zmiennoprzecinkowe mają większy sens. Chociaż istnieje teoretyczna „dokładnie 1,25 metra”, tak naprawdę nigdy się nie wydarzy: z pewnością nigdy nie będziesz w stanie zmierzyć dokładnych długości i prawdopodobnie nie będą istnieć nawet na poziomie atomowym. Jesteśmy przyzwyczajeni do pewnej tolerancji.

Społeczność
źródło
+1 za jasne i zwięzłe wyjaśnienie matematyczne. Aby odpowiedzieć na bardziej ogólną wersję pytania postawionego w tytule, przykładem liczby nie reprezentowalnej w bazie 10 jest 1/3.
Doval,
@Doval Podejrzewam, że w moim rozumowaniu lub wyjaśnieniach jest pewna usterka, którą mogłaby wskazać osoba bardziej zorientowana na matematykę ... ale wydaje mi się, że jestem na dobrej drodze, jeśli tak jest.
„Względnie pierwszy” w tym przypadku oznacza po prostu „nie czynnik”, prawda? Czy brakuje mi głębszej relacji matematycznej?
Patrick M,
1
Ach, tak jak rozumiem n = 15i b = 10nie są względnie pierwsze („nie dzielą żadnych wspólnych pozytywnych czynników (dzielników) z wyjątkiem 1”), ponieważ dzielą 5 jako czynnik. Kluczem jest to, że nie wszystkie czynniki 15 (5 i 3) nie są również czynnikami 10. (Poza tym: czy istnieje słowo wskazujące liczby, które dzielą lub nie dzielą wszystkich wspólnych czynników?) Myślę, że jest to zgrabnie Owinięte w twoje k, n, mrównanie, ale żeby naprawdę owinąć wokół niego głowę, musiałbym zobaczyć trójwymiarową fabułę. Niezależnie od tego, zasłużony +1 dla ciebie.
Patrick M,
1
@PatrickM: „Poza tym: czy istnieje słowo wskazujące liczby, które dzielą lub nie współużytkują wszystkie wspólne czynniki?”: Jakakolwiek liczba całkowita jest czynnikiem samym w sobie, więc jeśli wszystkie czynniki m są współczynnikami n , to w trywialny sposób wynika z tego m jest współczynnikiem n . Jednym z terminów na to, jak wyraźnie wiesz, jest czynnik . Kolejnym jest dzielnik .
ruakh
6

Gdy znajdziesz się poza zakresem dopuszczalnych wartości, odpowiedź brzmi tak. To powiedziawszy, prawie wszystko w zakresie będzie miało reprezentację. C # Odniesienie dziesiętne Chociaż nie podano tego w specyfikacji, liczb niewymiernych nie można dokładnie przedstawić (np. E 1 , pi, pierwiastek kwadratowy z 2 itd.).

Słowo dziesiętne oznacza 128-bitowy typ danych. W porównaniu do typów zmiennoprzecinkowych, typ dziesiętny ma większą precyzję i mniejszy zakres, co czyni go odpowiednim do obliczeń finansowych i pieniężnych. Przybliżony zakres i dokładność typu dziesiętnego pokazano w poniższej tabeli.

Precyzja: 28–29 cyfr znaczących

1 Podziękowania dla MichaelT za przypomnienie mi innej irracjonalnej liczby.

Adam Zuckerman
źródło
2
@Magus weź pod uwagę liczbę niewymierną e(2,71 ...). Log naturalny - ln (x) jest podstawą logu e. Zatem irracjonalne podstawy istnieją i są użyteczne. Szczególnej użyteczności base pi, nie jestem pewien - ale to nie znaczy, że gdzieś jej nie używa.
6
@Max, coraz bardziej zabłąkasz się w pytania matematyczne. Może się okazać, że jeśli liczba jest nieracjonalna w bazie 10, to czy jest irracjonalna w innych bazach? być użyteczną lekturą i punktem wyjścia do dalszych pytań z teorii liczb.
2
1/3 nie jest irracjonalne.
Adam Zuckerman
2
OP zapytał o bazę 10 (dziesięć). Stworzenie podstawy systemu liczbowego czegokolwiek pozwoli ci wyrazić dowolną liczbę jako 10. Na podstawie artykułu z Wikipedii użycie irracjonalnej liczby jako podstawy nie czyni z niej racjonalnej. Liczby wymierne można wyrazić jako liczby całkowite zarówno dla licznika, jak i mianownika, powtarzając liczby dziesiętne lub skończone zakończenie liczb dziesiętnych.
Adam Zuckerman
5
@FrustratedWithFormsDesigner Irracjonalność nie ma nic wspólnego z zasadami. Cóż, to przesada, ale to irracjonalność ma wpływ na reprezentację liczby w różnych podstawach (np. Czy ma nieskończone, powtarzające się cyfry), a nie na odwrót. Przeczytaj pytanie matematyczne powiązane z powyższym: math.stackexchange.com/questions/625473/…
1

Typ zmiennoprzecinkowy typu base-two byłby w stanie precyzyjnie przedstawić wiele wartości, których typ typu dziesiętnego o tym samym rozmiarze nie mógłby. Każda wartość, która byłaby dokładnie reprezentowana przez typ podstawy 2 o pewnym rozmiarze, byłaby dokładnie reprezentowana w typie podstawy 10 o wystarczającej wielkości. Wymagany rozmiar dla typu czysto dziesiętnego do reprezentowania wszystkich wartości binarnej liczby zmiennoprzecinkowej zależałby od zakresu wykładniczego typu binarnego; setki bitów za float, lub tysiące za double.

To powiedziawszy, Decimaltyp jest na tyle duży, że można by go uczynić użytecznym jako typ „uniwersalny” zdolny do zachowania wartości dowolnego innego liczbowego prymitywu i dostarczenia innych dodatkowych funkcji oprócz (jeśli nic więcej, użyj jednego bitu aby wskazać, czy zapamiętana wartość jest wynikiem konwersji a double, a jeśli ten bit jest ustawiony, należy użyć 64 bitów do przechowywania danej wartości). Microsoft jednak tego nie zrobił. W rezultacie, konwersja doubledo Decimalcałkowicie nie do dużych wartości powoduje małe wartości zaokrągla do najbliższej 1E-28. Ponadto, nawet w zakresie dynamicznymdecimal, metoda konwersji nie będzie „w obie strony”. Na przykład ocena 1,0 / 3,0 jako podwójna da 0,33333333333333333148, ale konwersja na dziesiętną da 0,3333333333333333m, a konwersja z powrotem na podwójną da 0,33333333333333329818.

supercat
źródło