Pułapki liczb zmiennoprzecinkowych Adam Sawicki – asawicki.infoasawicki.info

Slides:



Advertisements
Podobne prezentacje
Tablice 1. Deklaracja tablicy
Advertisements

Metody numeryczne część 1. Rozwiązywanie układów równań liniowych.
Zmienne i Typy.
Reprezentacja danych w komputerze
Operacje zmiennoprzecinkowe
Filip Andrzejewski Remigiusz Chiluta
Języki programowania C++
Sortowanie na stercie Heap Sort
Metody numeryczne Wykład no 1.
Materiały pochodzą z Platformy Edukacyjnej Portalu
Instrukcje warunkowe Zajęcia 5.
Liczby Pierwsze - algorytmy
Liczby wokół nas A. Cedzidło.
Pisemne dzielenie liczb naturalnych
Programowanie imperatywne i język C Copyright, 2004 © Jerzy R. Nawrocki Wprowadzenie.
Programowanie imperatywne i język C
Programowanie imperatywne i język C Copyright, 2005 © Jerzy R. Nawrocki Wstęp.
Programowanie imperatywne i język C Copyright, 2004 © Jerzy R. Nawrocki Wprowadzenie.
1 Dygresja: cztery płyty główne…. 2 Dygresja: osobliwości C /* cos o nieistniejacym typie Boolean */ /* oraz o operatorze przecinkowym */ #include int.
Typy standardowe Typ Boolean Typ Integer Typ Float Typ Character Operacje wejścia-wyjścia.
Liczby całkowite.
ZBIÓR LICZB RZECZYWISTYCH I JEGO PODZBIORY
Wyrażenia Wyrażenie w Fortranie jest poprawną syntaktycznie kombinacją zmiennych, stałych, operatorów i funkcji. Wyrażenia są jednozdaniowymi przepisami.
Rozkład normalny Cecha posiada rozkład normalny jeśli na jej wielkość ma wpływ wiele niezależnych czynników, a wpływ każdego z nich nie jest zbyt duży.
Jak uczę programowania?
Zapis informacji Dr Anna Kwiatkowska.
Ułamki zwykłe i liczby mieszane.
Reprezentacje - zmiennoprzecinkowa
Programowanie imperatywne i język C Copyright, 2006 © Jerzy R. Nawrocki Wstęp do.
„Są plusy dodatnie i plusy ujemne.”
Aleksandra Duchnowicz kl. 6.d
Podstawy programowania
POJĘCIE ALGORYTMU Pojęcie algorytmu Etapy rozwiązywania zadań
Technika Mikroprocesorowa 1
opracowanie: Agata Idczak
Podstawy programowania
Reprezentacja stało i zmiennopozycjna
Zastosowania ciągów.
Programowanie strukturalne i obiektowe
Dane INFORMACYJNE Nazwa szkoły:
Programowanie strukturalne i obiektowe
Architektura systemów komputerowych
Liczby całkowite dodatnie BCN
Źródła błędów w obliczeniach numerycznych
Stało- i zmiennopozycyjna reprezentacja liczb binarnych
Matematyka i system dwójkowy
Podstawy języka Instrukcje - wprowadzenie
Programowanie strukturalne i obiektowe C++
Podstawy arytmetyki komputerowej Paweł Perekietka
Temat 4: Typy danych.
WYKŁAD 3 Temat: Arytmetyka binarna 1. Arytmetyka binarna 1.1. Nadmiar
Zmienne i typy danych w C#
POZNAJ ŚWIAT LICZB CAŁKOWITYCH
Typy danych, klucz podstawowy, klucz obcy
Wybrane aspekty programowania w C++ (i nie tylko)
Działania na ułamkach dziesiętnych
Zasady arytmetyki dwójkowej
Typy liczbowe, zmienne, operatory Zajęcia 4. Zmienne Zmienna – to w programowaniu element programu, który może mieć przypisaną pewną wartość (wartość.
Programowanie imperatywne i język C Copyright, 2007 © Jerzy R. Nawrocki Wstęp do.
METODY REPREZENTOWANIA IFORMACJI
CZYM JEST KOD BINARNY ?.
Wstęp do programowania Wykład 2 Dane, instrukcje, program.
 Formuła to wyrażenie algebraiczne (wzór) określające jakie operacje ma wykonać program na danych. Może ona zawierać liczby, łańcuchy znaków, funkcje,
Liczby 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, …(i tak dalej) nazywamy liczbami naturalnymi. Tak jak z liter tworzy się słowa, tak z cyfr tworzymy liczby. Dowolną.
Liczbami naturalnymi nazywamy liczby 0,1,2,3,..., 127,... Liczby naturalne poznaliśmy już wcześniej; służą one do liczenia przedmiotów. Zbiór liczb.
URZĄDZENIA TECHNIKI KOMPUTEROWEJ Zapis liczb binarnych ze znakiem.
Zmienne typy danych w VBA. MS Excel – typy danych w języku programowania VBA.
Liczba π Aleksandra Tera 6F.
Podstawy Informatyki.
Technika Mikroprocesorowa 1
Zapis prezentacji:

Pułapki liczb zmiennoprzecinkowych Adam Sawicki – asawicki.infoasawicki.info

Agenda Liczby zmiennoprzecinkowe – Budowa – Typy – możliwości i ograniczenia – Typy – w językach programowania Pułapki – Zakres – Precyzja – Nieskończone rozwinięcie – Liczby całkowite – Porównywanie – Wartości specjalne Podsumowanie Ciekawostka: half-float 2

Liczby zmiennoprzecinkowe Liczby zmiennoprzecinkowe (floating point numbers) – Przybliżona reprezentacja liczb rzeczywistych – Mogą zawierać część całkowitą i ułamkową – Mogą przyjmować bardzo duże lub małe wartości Standard IEEE 754 – Wspierane sprzętowo przez procesor – Dostępne w różnych językach programowania 3

Liczby zmiennoprzecinkowe Przydatne narzędzie: IEEE 754 ConverterIEEE 754 Converter · 2 3 · = Znak Wykładnik Mantysa

Typy – możliwości i ograniczenia 5 Floating-Point Formats asawicki.info

Typy – możliwości i ograniczenia Dwa najpopularniejsze: 32- i 64-bitowy Nazywane „pojedynczej” i „podwójnej” precyzji 6

Typy – w językach programowania Język32-bit Float64-bit Float C, C++ *floatdouble C#floatdouble Javafloatdouble Delphi/Object PascalSingleDouble SQLREALFLOAT Python *float PHP *float JavaScript **Number Lua **number 7 * Zazwyczaj – zależnie od implementacji ** Jedyny dostępny typ liczbowy, nie ma typów całkowitych

Zakres Ograniczony zakres możliwych do zapisania wartości Wartość najbliższa zero Wartość największa/najmniejsza Jest szeroki, rzadko stanowi problem 8

Precyzja Precyzja określana jest liczbą cyfr znaczących Binarnych – to liczba bitów mantysy + 1 Dziesiętnych – podawana w przybliżeniu 9

Precyzja Precyzja jest względna Różnice między sąsiednimi możliwymi do zapisania wartościami są tym większe, im większa jest wartość liczbowa. Wartości te rozmieszczone są „gęściej” w okolicy zera. 10 float x = f; printf("%.16g\n", x);

Precyzja – przykład timeGetTime zwraca czas od startu systemu, w milisekundach. Ile wynosi precyzja wyniku? Co jest źle w tym przykładzie? Jak to naprawić? 11 #include int main() { float poczatek = (float)timeGetTime() / f; DlugaOperacja(); float koniec = (float)timeGetTime() / f; printf("DlugaOperacja trwala: %g s\n", koniec - poczatek); }

Precyzja – przykład Jest to przykład tzw. catastrophic cancellation Zmienne poczatek i koniec mogą mieć duże wartości. Niewielka różnica między nimi może być niedokładna przez ograniczenia pracyzji. 12 Czas od startu systemuPrecyzja zmiennej 1 s119 ns s (3 godziny)1 ms s (1 dzień)7.81 ms

Precyzja – przykład Rozwiązaniem jest zachować czasy w ich natywnym typie, a dopiero ich różnicę zamienić na typ float. Podobnie precyzyjny czas z funkcji QueryPerformanceCounter warto pozostawić jako 64- bitowy integer. 13 int main() { DWORD poczatek = timeGetTime(); DlugaOperacja(); DWORD koniec = timeGetTime(); float czasTrwania = (float)(koniec - poczatek) / f; printf("DlugaOperacja trwala: %g s\n", czasTrwania); }

Nieskończone rozwinięcie Liczba mająca skończone rozwinięcie w zapisie dziesiętnym niekoniecznie ma takie w zapisie binarnym. 14 LiczbaSystem dziesiętnySystem binarny 1 + 1/ π … … 1/ … (!)

Liczby całkowite Wartości całkowite są w typach zmiennoprzecinkowych reprezentowane dokładnie… Operacje na nich (dodawanie, odejmowanie, mnożenie) także dają dokładny wynik. Dzięki temu można ich używać zamiast liczb całkowitych (jak w JavaScript, Lua). 15 float a = 256, b = 13; printf("%g\n", a * b);

Liczby całkowite …jednak tylko do pewnej wartości maksymalnej! Powyżej tej wartości zaczynają „przeskakiwać” co 2, potem co 4 itd. Zakres dokładnych liczb całkowitych w X-bitowym float jest mniejszy, niż w X-bitowym integer. Zakres dokładnych liczb całkowitych w 64-bitowym float obejmuje cały zakres 32-bitowych integer. 16

Porównywanie Wyników obliczeń nie należy porównywać operatorem == ani != Niedokładności na ostatnich miejscach po przecinku mogą spowodować, że liczby nie będą identyczne. 17 #include int main() { float a = 1.0f / 10.0f; float b = 1.0f - 0.9f; printf("a=%g, b=%g\n", a, b); if (a == b) printf("Zgadza sie.\n"); else printf("Nie zgadza sie!\n"); }

Porównywanie a = 0x3dcccccd ≈ b = 0x3dccccd0 ≈ #include int main() { float a = 1.0f / 10.0f; float b = 1.0f - 0.9f; printf("a=%g, b=%g\n", a, b); if (a == b) printf("Zgadza sie.\n"); else printf("Nie zgadza sie!\n"); }

Porównywanie Rozwiązaniem jest porównywanie z pewnym małym marginesem ±ε Ile powinien wynosić? To trudne pytanie. Zależy od rzędu wielkości wyniku i spodziewanych błedów. 19 #include int main() { float a = 1.0f / 10.0f; float b = 1.0f - 0.9f; printf("a=%g, b=%g\n", a, b); if (fabsf(b - a) < f) printf("Zgadza sie.\n"); else printf("Nie zgadza sie!\n"); }

Wartości specjalne Wartość zmiennoprzecinkowa może być jednego z kilku rodzajów, oprócz wartości normalnej (normal): Zero – Są dwa zera, zależnie od bitu znaku: +0 i -0. – Są sobie równe (+0 == -0), więc nie trzeba się nimi zajmować. Wartość zdenormalizowana (denormal, subnormal) – Pozwala zapisać wartość jeszcze mniejszą (bliższą zero), niż normalna. – Po prostu działa – nie trzeba się nią zajmować. 20

Wartości specjalne INF – nieskończoność (od Infinity) – Również ma dwie wartości: +INF i -INF. – Oznacza przepełnienie ponad maksymalną wartość lub matematyczną nieskończoność ∞. – Drukowana jako „1.#INF” lub „inf”. NaN – „nie liczba” (od Not a Number) – Wartość niemożliwa do określenia, błąd obliczeń – np. wynik niedozwolonej operacji. – Drukowana jako „1.#IND” (od indeterminate – nieokreślony) lub „nan” itp. 21

Wartości specjalne – test 22 #include int main() { double zero = 0.0; double dwa = 2.0; printf(" 2 / 0 = %g\n", dwa / zero); printf("-2 / 0 = %g\n", -dwa / zero); printf(" 0 / 0 = %g\n", zero / zero); printf("log(0) = %g\n", log(zero)); printf("log(-2) = %g\n", log(-dwa)); printf("sqrt(-2) = %g\n", sqrt(-dwa)); double inf = dwa / zero; double nan = zero / zero; printf(" 2 + INF = %g\n", dwa + inf); printf(" 2 * INF = %g\n", dwa * inf); printf("-2 * INF = %g\n", -dwa * inf); printf(" 0 * INF = %g\n", zero * inf); printf(" 2 / INF = %g\n", dwa / inf); printf(" 0 / INF = %g\n", zero / inf); printf("INF + INF = %g\n", inf + inf); printf("INF - INF = %g\n", inf - inf); printf("INF * INF = %g\n", inf * inf); printf("INF / INF = %g\n", inf / inf); printf("2 + NaN = %g\n", dwa + nan); printf("2 * NaN = %g\n", dwa * nan); printf("2 / NaN = %g\n", dwa / nan); printf(" INF > 2 = %s\n", inf > dwa ? "true" : "false"); printf("-INF < 2 = %s\n", -inf < dwa ? "true" : "false"); printf("2 == NaN = %s\n", dwa == nan ? "true" : "false"); printf("NaN == NaN = %s\n", -nan == nan ? "true" : "false"); }

Wartości specjalne – test 23

Wartości specjalne INF i NaN zachowują się zgodnie z zasadami matematyki – Każda operacja z NaN w wyniku daje NaN – Każde porównanie z NaN daje false (nawet z samym sobą) Teoretycznie możnaby je wykorzystywać – Wykrywać? Jawnie przypisywać? W praktyce oznaczają błąd obliczeń – Niespodziewane zero, liczba ujemna, bardzo duża lub bardzo mała – Należy im zapobiegać 24

Podsumowanie Liczby zmiennoprzecinkowe są przybliżeniem liczb rzeczywistych – Mają złożoną budowę – Mają ograniczony zakres i precyzję Warto być świadomym ich cech i ograniczeń – Nie każdą liczbę da się zapisać dokładnie – Im większa wartość, tym większy bezwzględny błąd – Wyniki obliczeń mogą się różnić od spodziewanych na dalszych miejscach po przecinku – Nie należy ich porównywać operatorem == ani !=, ale ±ε – Wartości specjalne INF, NaN oznaczają błąd obliczeń 25

Ciekawostka: half-float Typ zmiennoprzecinkowy 16-bitowy – precyzji „połówkowej” Bardzo ograniczone możliwości – Zakres: maksimum to – Precyzja: ok. 3 cyfr dziesiętnych – Wciąż większy zakres i precyzja, niż bajt 0…255 Brak wsparcia sprzętowego w CPU – Wsparcie sprzętowe w nowych GPU – Wykorzystywany w grafice do zapisywania kolorów RGB 26

Pytania? 27