Skocz do zawartości

Temat został przeniesiony do archiwum

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

Zainfekowany

Dziwne zaokrąglanie liczb?

Rekomendowane odpowiedzi

Napisać program wczytujący ciąg liczb rzeczywistych z

klawiatury (dowolny ciąg max 100 liczb). Liczby te należy zapisywać do tablicy float tab[100]. Następnie należy wyznaczyć wartość średnią i maksymalną tych liczb. Wczytywanie jest realizowane do momentu kiedy użytkownik wprowadza liczby (wtedy scanf(‘’%f”,&liczba)==1). Po wprowadzeniu litery lub znaku specjalnego program kończy wczytywanie liczb do tablicy i prezentuje wyniki. Wskazówka: zacznij od napisania programu który zawsze wczyta dokładnie 10 liczb

 

 

 

Mam pytanie, realizuję powyższe zadanie i dlaczego w takim kodzie, tzn. wczytuję dopóki użytkownik podaje liczby, a zaś jak narazie je wypisuję, to po wpisaniu przez użytkownika nie liczby, mam jakieś dziwne przybliżenie ostatniego elementu?

 

http://wklej.org/id/1496282/

 

Wpiszcie sobie np. 41, 85.5555, L

 

i otrzymacie: 41.000000, 85.555496

 

Skąd to się bierze?

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

To wynika ze sposobu w jaki zapisywana jest liczba zmiennoprzecinkowa. Większość liczb w tym formacie jest zapisywana jako przybliżenie, stąd dziwna wartość.

Użyj wypisywania większej ilości cyfr po przecinku aby się o tym przekonać: printf("%.15f\n", liczba);

Tak "proste" liczby jak 0.1 nie mają dobrej reprezentacji w tym typie, w związku z tym suma dziesięciu wartości 0.1 nie będzie wcale równa 1.

Dlatego też przy operacjach na typach zmiennoprzecinkowych nigdy się nie używa porównań == !=, a sprawdza czy liczba nie zawiera się w przedziale zależnym jak jakiegoś epsilon (względnie małej wartości określającej zakres błędu).

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Dlatego też przy operacjach na typach zmiennoprzecinkowych nigdy się nie używa porównań == !=, a sprawdza czy liczba nie zawiera się w przedziale zależnym jak jakiegoś epsilon (względnie małej wartości określającej zakres błędu).

 

Ale o jakie porównania dokładnie ci chodzi?

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

	int times = 10;
float suma = 0, jeden = 1;
while(times--)
	suma += 0.1;
printf("%.15f %.15f\n", suma, jeden);
printf("czy liczby sa takie same? %d", suma == jeden);

co wypisuje:

1.000000119209290 1.000000000000000

czy liczby sa takie same? 0

0 znaczy fałsz, czyli liczby nie są takie same. Umieściłbyś taki warunek w if'ie i byś się głowił o co chodzi ;)

Jest sporo materiałów w sieci na temat tego jak dobrze korzystać z liczb zmiennoprzecinkowych, np tutaj: Klik.

 

Jest to jeden z powodów dla których float/double są "złe" i powinno się ich unikać jeżeli nie są koniecznie potrzebne.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Nie do końca z tym unikaniem double/float.

 

Je się stosuje, tam gdzie reprezentacja dziesiętna nie jest koniecznością (np. pomiary fizyczne, które są z natury obarczone błędem). Unika się ich tam, gdzie są np. obliczenia finansowe, czyli reprezentacja dziesiętna jest z góry narzucona np. przez waluty i fakt, że np. 0.1 ma de facto nieskończone rozwinięcie binarne, może być poważnym problemem przy operacjach (zwłaszcza wielokrotnie powtarzanych).

 

No i jest też fakt, że double/float praktycznie zawsze są wydajniejsze niż decimal.

 

Odpowiednie narzędzie do odpowiednich zadań, do innych nieodpowiednie, nie polegać na intuicji, tylko na konkretnej znajomości reprezentacji i konsekwencjach tejże.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

  • Ostatnio przeglądający   0 użytkowników

    Brak zarejestrowanych użytkowników przeglądających tę stronę.

×
×
  • Dodaj nową pozycję...