Czytałem artykuł z firmy Microsoft dotyczącą Poszerzenie konwersji i Option Strict On , gdy dostałem się do części
Następujące konwersje mogą stracić precyzję:
- Integer to Single
- Długi do pojedynczego lub podwójnego
- Dziesiętny na pojedynczy lub podwójny
Jednak te konwersje nie tracą informacji ani wielkości.
.. ale zgodnie z innym artykułem dotyczącym typów danych ,
Typ liczby całkowitej może przechowywać od -2.147.483.648 do 2.147.483.647 i
Jeden typ może przechowywać od
- Od 1,401298E-45 do 3,4028235E + 38 dla liczb dodatnich,
- i -3,4028235E + 38 do - 1,401298E-45 dla liczb ujemnych
.. więc Single może przechowywać znacznie więcej liczb niż Integer. Nie mogłem zrozumieć, w jakiej sytuacji taka konwersja z Integer na Single może stracić precyzję. Czy mógłby ktoś wyjaśnić?
źródło
Integer
s (99,2%) nie może być reprezentowany jakoSingle
, więc „kiedy” jest „prawie zawsze”.Single
może reprezentować tylko 4 278 190 079 różnych liczb.Single
Wartość reprezentuje numer wtedy i tylko wtedy, gdy przechowywane wykładnik od 255, co oznacza, że istnieje 255 * 2 ^ 24Single
s reprezentujące numery. Spośród nich dwa z nich reprezentują tę samą liczbę (mianowicie zero), a pozostałe wszystkie reprezentują różne liczby.[-16777216,16777216]
(2 ^ 24 = znaczenie i szerokość) mogą być dokładnie przedstawione. Większe liczby są zaokrąglane do najbliższej wielokrotności 2, 4, 8, ... w zależności od ich wielkości.Single
ma dwa sposoby przechowywania zera.Single
Może więc w rzeczywistości reprezentować mniej wyraźnych liczb niżInteger
.Typy zmiennoprzecinkowe (takie jak Single i Double) są reprezentowane w pamięci przez znak, mantysę i wykładnik potęgi. Potraktuj to jako notację naukową:
Używają - jak można się spodziewać - podstawy 2. Istnieją inne poprawki, które pozwalają na reprezentowanie nieskończoności i NaN, a wykładnik jest przesunięty (wróci do tego), a stenografia dla mantysy (również do tego wróci) . Poszukaj standardu IEEE 754, który obejmuje jego reprezentację i operacje, aby uzyskać więcej szczegółów.
Dla naszych celów możemy sobie wyobrazić go jako liczbę binarną „mantysa” i „wykładnik”, który mówi ci, gdzie umieścić separator dziesiętny.
W przypadku singla mamy 1 bit na znak, 8 na wykładnik i 23 na mantysę.
Rzecz w tym, że będziemy przechowywać mantysę od najbardziej znaczącej cyfry. Pamiętaj, że wszystkie zera po lewej stronie nie są istotne. Biorąc pod uwagę, że pracujemy w trybie binarnym, wiemy, że najbardziej znaczącą cyfrą jest 1 ※. Skoro wiemy o tym, nie musimy go przechowywać. Dzięki temu skrótowi efektywny zasięg mantysy wynosi 24 bity.
※: Chyba że liczba, którą przechowujemy, wynosi zero. W tym celu wszystkie bity zostaną ustawione na zero. Jeśli jednak spróbujemy zinterpretować to pod podanym przeze mnie opisem, otrzymamy 2 ^ 24 (domyślną 1) pomnożoną przez 1 (2 do potęgi wykładnika 0). Tak więc, aby to naprawić, wykładnik zera jest wartością specjalną. Istnieją również specjalne wartości do przechowywania nieskończoności i NaN w wykładniku.
Zgodnie z przesunięciem wykładnika - oprócz unikania specjalnych wartości - przesunięcie pozwala na umieszczenie kropki dziesiętnej przed początkiem mantysy lub po jej zakończeniu, bez potrzeby posiadania znaku dla wykładnika.
Oznacza to, że w przypadku dużych liczb typ zmiennoprzecinkowy umieści przecinek dziesiętny poza końcem mantysy.
Pamiętaj, że mantysa jest liczbą 24-bitową. Nigdy nie będzie reprezentował 25-bitowej liczby ... nie ma tego dodatkowego bitu. Zatem singiel nie może rozróżnić między 2 ^ 24 a 2 ^ 24 + 1 (są to pierwsze 25 bitów, i różnią się w ostatnim bicie, który nie jest reprezentowany w singlu).
Zatem dla liczb całkowitych zasięg singla wynosi od -2 ^ 24 do 2 ^ 24. A próba dodania 1 do 2 ^ 24 spowoduje 2 ^ 24 (ponieważ jeśli chodzi o typ, 2 ^ 24 i 2 ^ 24 + 1 mają tę samą wartość). Wypróbuj online . Dlatego podczas konwersji z liczby całkowitej na liczbę pojedynczą występuje utrata informacji. I właśnie dlatego pętla, która korzysta z pojedynczego lub podwójnego, może być pętlą nieskończoną bez zauważenia.
źródło
1
bitu wiodącego w znaczeniu. Wynika to z faktu, że pole tendencyjnego wykładnika jest niezerowe . Subnormale (znane również jako denormale), w tym+-0.0
mają wiodący0
bit swojego znaczenia. Wydaje mi się, że można uprościć rozważenie0.0
całkowicie specjalnego przypadku, ale w0.0
rzeczywistości stosuje się te same reguły kodowania, co inne podnormale.Oto rzeczywisty przykład konwersji z
Integer
naSingle
może stracić precyzję:Single
Typu może przechowywać wszystkie liczby całkowite od -16777216 do 16.777.216 (włącznie), ale nie można zapisać wszystkie liczby całkowite poza tym zakresem. Na przykład nie może przechowywać liczby 16777217. W tym przypadku nie może przechowywać żadnych liczb nieparzystych większych niż 16777216.Możemy użyć Windows PowerShell, aby zobaczyć, co się stanie, jeśli przekonwertujemy
Integer
naSingle
ai wstecz:Zauważ, że 16777217 zaokrąglono w dół do 16777216, a 16777219 zaokrąglono w górę do 16777220.
źródło
float
s stale rośnie jako potęgi. en.wikipedia.org/wiki/…Typy zmiennoprzecinkowe są podobne do „notacji naukowej” w fizyce. Liczba jest podzielona na bit znaku, wykładnik potęgi (mnożnik) i mantysę (cyfry znaczące). Zatem wraz ze wzrostem wielkości wartość zwiększa się również rozmiar kroku.
Zmienny punkt zmienny o pojedynczej precyzji ma 23 bity mantysy, ale istnieje „domyślny 1”, więc mantysa ma w rzeczywistości 24 bity. Dlatego wszystkie liczby całkowite o wielkości do 2 24 mogą być przedstawione dokładnie w zmiennoprzecinkowym pojedynczej precyzji.
Powyżej tego mogą być reprezentowane kolejno mniejsze liczby.
Tak więc spośród 2 32 możliwych 32-bitowych liczb całkowitych ze znakiem tylko 2 * (2 24 + 7 * 2 23 ) = 9 * 2 24 może być reprezentowane w zmiennoprzecinkowym pojedynczej precyzji. To 3,515625% całości.
źródło
Pływaki pojedynczej precyzji mają 24 bity precyzji. Wszystko ponad to jest zaokrąglane do najbliższej liczby 24-bitowej. Może być łatwiejsze do zrozumienia w dziesiętnej notacji naukowej, ale należy pamiętać, że rzeczywiste zmiennoprzecinkowe używają plików binarnych.
Załóżmy, że masz 5 cyfr dziesiętnych pamięci. Możesz użyć takich jak zwykłe int bez znaku, co pozwala mieć dowolną liczbę od 0 do 99999. Jeśli chcesz być w stanie reprezentować większe liczby, możesz użyć notacji naukowej i po prostu przydzielić dwie cyfry jako wykładnik, więc możesz teraz reprezentować wszystko od 0 do 9,99 x 10 99 .
Jednak największa liczba, którą możesz dokładnie przedstawić, to teraz tylko 999. Jeśli próbujesz reprezentować 12345, możesz uzyskać 1,23 x 10 4 lub 1,24 x 10 4 , ale nie możesz reprezentować żadnej z liczb pośrednich, ponieważ nie ma wystarczającej liczby dostępnych cyfr.
źródło