matematykaszkolna.pl
Program C# ozone: Podpowie mi ktoś gdzie mam błąd? Zadanie: Należy wczytać ciąg liczb rzeczywistych. Wczytywanie należy zakończyć gdy pojawi się liczba 0. Obliczyć sumę wczytanych liczb. Program: #include <stdio.h> int main() { float n; float k=0; do{ printf("n= "); scanf("%f",n); k=k+n; } while(n!=0);{ printf("wynik:%f", k); } getch(); return 0; }
4 kwi 12:56
Patronus: nie znam dobrze języka, ale algorytm wydaję się ok − a co ci dokładnie nie działa? Źle wczytuje czy jest błąd przy kompilacji?
4 kwi 13:05
xcv: no właśnie problem w tym, że wczytuje mi n i gdy za n dam 0 to kończy mi program i nie wyświetla wyniku jakby w ogóle pomijał printf("wynik:%f", k);
4 kwi 13:08
ozone: Napisałem to jeszcze w ten sposób: #include <stdio.h> int main() { float n; float k=0; do{ k=k+n; printf("n= "); scanf("%f",&n); if(n==0){ printf("wynik %f", &k); } } while(n > 0); return 0; } Tym razem wyswietla mi np: n=2.2 n=1 n=3 n=0 wynik 0.00000 O co w tym chodzi?
4 kwi 14:30
ozone: *k=k+n; powinno być 2 linie niżej
4 kwi 14:33
Trivial: Masz & w printfie oraz to o czym mówiłeś: k = k+n jest za wysoko. Program działa, choć porównywanie floatów w stylu x == 0 jest bardzo niebezpieczne. http://ideone.com/TeFEUM
4 kwi 16:26
ozone: Wyświetla cały czas wynik 0.000 obojętnie jakie n podam w takim razie to wina kompilatora? No i w jaki inny sposób zapisać to o czym mówisz x == 0 ?
4 kwi 17:26
ozone: Ok już wszystko działa dzięki wielkie ale nadal interesuje mnie dlaczego porównywanie w ten sposób może szkodzić
4 kwi 17:37
Trivial: Takie porównywanie to zła praktyka dlatego, że liczby zmiennoprzecinkowe mają jeden bardzo poważny problem − są niedokładne (wynik jest zaokrąglany/obcinany). Dochodzi jeszcze rozróżnienie między float (0.1f) a double (0.1). Oto przykład: http://ideone.com/rH1dxn
4 kwi 18:45
Trivial: Prymitywnym rozwiązaniem tego problemu to warunek |x − x*| < ε, np.: double eps = 0.000001; if (fabs(x − 0.1) < eps) { ok; }
4 kwi 18:50
ozone: Hmm dopiero zaczynam przygodę z programowaniem ale mniej więcej wiem o co Ci chodzi. Przeanalizuję sobie ten przykład jeszcze jak poznam więcej podstaw. zabrałem się za to dopiero od wczoraj emotka No i dzięki za pomoc.
4 kwi 20:01
Trivial: Nie musisz wiedzieć jak działa program, który to testuje. Interesują Cię tylko wyniki. emotka
4 kwi 20:07
ozone: W takim razie chodziło tam o to, że jak wykonujemy operacje na zmiennych float i double to wychodzą różne wyniki?
4 kwi 20:09
ozone: %−25s − to oznacza że zczytuje jakąś część wartości argumentu funkcji test?
4 kwi 20:18
Trivial: Jak mówiłem, nie musisz wiedzieć jak działa makro TEST. Ono po prostu wypisuje OK jeśli równość zachodzi i FAIL jeśli nie zachodzi. %−25s to specyfikator formatu funkcji printf (taki jak %f, ale rozbudowany): % → znacznik − → wyrównaj do lewej 25 → wypisany ciąg powinien mieć długość co najmniej 25 znaków s → typ zmiennej to łańcuch znakowy. #x → argument w postaci łańcucha znakowego (kod) (x) → wartość warunku (x) ? "OK" : "FAIL" → jeśli (x) to "OK", w przeciwnym razie "FAIL". Mało istotne! Ważne są wyniki działania tego programiku. emotka Np. to, że 1.1 − 0.1 == 1.0 jest OK, ale już 0.11 − 0.1 == 0.01 nie jest. Dzieje się tak dlatego, że liczby zmiennoprzecinkowe są przechowywane w postaci binarnej. W zapisie dwójkowym 0.1 jest tak naprawdę ułamkiem okresowym. 0.1 (dec) = 0.000110011001100110011001100110011.... (bin) Oraz: 0.11 (dec) = 0.000111000010100011110101110000101.... (bin) Przechowywana jest skończona wartość tej postaci (ucinamy na pewnym bicie). Przy wykonywaniu odejmowania 0.11 − 0.1 błędy zaokrągleń nie dają dokładnego wyniku 0.01 i warunek 1.1 − 0.1 == 1.0 nie zachodzi.
4 kwi 20:38
Trivial: Miało być 0.11 − 0.1 == 0.01 nie zachodzi. 1.1 − 0.1 == 1.0 zachodzi − widocznie tutaj te błędy się jakoś skracają. emotka Dlatego nie powinno się sprawdzać równości liczb zmiennoprzecinkowych − trzeba być ekspertem obliczeń numerycznych, żeby wiedzieć co to porównanie dokładnie oznacza.
4 kwi 20:44
ozone: Swietnie wytlumaczone! emotka gdyby tak to tlumaczyli na wykladach ... emotka
4 kwi 21:57