-
1. Data: 2019-06-12 14:17:45
Temat: Porównywanie liczb, double float
Od: "Pszemol" <P...@P...com>
Witam, spędziłem wczoraj sporo godzin w biurze na debugowaniu
kodu napisanego przez naszego kontraktora i w końcu znalazłem buga.
Przyczyną błędu była różnica odejmowania dwu liczb całkowitych
wynosząca 15.1234e-15 :-)
Ale może więcej szczegółów podam:
Pisząc w Visual Basic 6 gostek porównywał rezultat konwersji CDbl()
stringu od którego odjął stałą numeryczną 1.8 do lokalnej zmiennej double.
Czyli mamy kod:
Sub AlaMaKota(nieważne tutaj argumenty procedury)
Dim len as Double
len = CDbl("tekst wydłubany z RS232") - 1.8
If len <> CDbl("inny tekst wydłubany z RS232) Then
zgłoś błąd i kapitulujemy... kaput!
Else
lecimy z testami talej, wsio w pariadkie
Endif.
Pierwszy tekst z RS232 był 32.8, drugi 31. 32.8-1.8 = 31.
Powinno być wszystko ok, bo w matematyce 31 równe jest 31 :-)
Wynik porównania VB6 był 31 nie jest równe 31 i program
kapitulował...
Po zamienieniu testu "if double <> double then" na test
"if double - double < -0.001 Or double - double > 0.001 then"
program zaczął pracować normalnie.
Przyczyną błędu była różnica odejmowania wynosząca 15.1234e-15
Dlaczego konwersja CDbl stringu 31 lub 32.8 dodaje jakieś
śmieci do zmiennej double float na 15 miejscu po przecinku??
A może odejmowanie stałej 1.8 wprowadza ten błąd?
Czy to jest normalne zachowanie się VB6?
Czy inne Visuale jak VC++ lub VC# też tak mają?
-
2. Data: 2019-06-12 14:29:41
Temat: Re: Porównywanie liczb, double float
Od: Mateusz Viste <m...@n...pamietam>
On Wed, 12 Jun 2019 07:17:45 -0500, Pszemol wrote:
> Pisząc w Visual Basic 6 gostek porównywał rezultat konwersji CDbl()
> stringu od którego odjął stałą numeryczną 1.8 do lokalnej zmiennej
> double.
Prawdziwi programiści nie używają liczb zmiennoprzecinkowych.
Obowiązkowa lektura na wieczór:
http://perso.ens-lyon.fr/jean-michel.muller/goldberg
.pdf
Mateusz
-
3. Data: 2019-06-12 14:44:39
Temat: Re: Porównywanie liczb, double float
Od: "J.F." <j...@p...onet.pl>
Użytkownik "Pszemol" napisał w wiadomości grup
dyskusyjnych:qdqqh6$n2f$...@d...me...
>Sub AlaMaKota(nieważne tutaj argumenty procedury)
>Dim len as Double
>len = CDbl("tekst wydłubany z RS232") - 1.8
>If len <> CDbl("inny tekst wydłubany z RS232) Then
> zgłoś błąd i kapitulujemy... kaput!
>Else
> lecimy z testami talej, wsio w pariadkie
>Endif.
>Pierwszy tekst z RS232 był 32.8, drugi 31. 32.8-1.8 = 31.
>Powinno być wszystko ok, bo w matematyce 31 równe jest 31 :-)
>Wynik porównania VB6 był 31 nie jest równe 31 i program
>kapitulował...
>Przyczyną błędu była różnica odejmowania wynosząca 15.1234e-15
>Dlaczego konwersja CDbl stringu 31 lub 32.8 dodaje jakieś
>śmieci do zmiennej double float na 15 miejscu po przecinku??
>A może odejmowanie stałej 1.8 wprowadza ten błąd?
>Czy to jest normalne zachowanie się VB6?
To nie jest problem VB, to jest problem przyjetego formatu liczb
rzeczywistych.
Albo problem programisty :-)
31 jest dokladne, 0.8 nie.
0.5 jest dokladne, 0.25 i 0.75 itd - ale wiekszosc liczb "dziesietnych
po przecinku" niestety nie.
Po prostu nie da sie zapisac 32.8 dokladnie.
Programista ma o tym wiedziec i sie zabezpieczyc :-)
>Czy inne Visuale jak VC++ lub VC# też tak mają?
To jest problem procesora z FP IEEEcostam.
Akurat .net ma dodatkowe formaty (Decimal), w ktorych powinno to
dzialac.
Tylko trzeba ie
Ale i tak bym dorzucil zabezpieczenie.
Problem promieniuje na bazy danych, gdzie mamy duzo kwot, a te grosze
tez nie sa dokladne :-)
J.
-
4. Data: 2019-06-12 14:47:06
Temat: Re: Porównywanie liczb, double float
Od: Wojciech Piechowski <p...@g...com>
W dniu środa, 12 czerwca 2019 14:17:44 UTC+2 użytkownik Pszemol napisał:
> Dlaczego konwersja CDbl stringu 31 lub 32.8 dodaje jakieś
> śmieci do zmiennej double float na 15 miejscu po przecinku??
> A może odejmowanie stałej 1.8 wprowadza ten błąd?
>
> Czy to jest normalne zachowanie się VB6?
>
> Czy inne Visuale jak VC++ lub VC# też tak mają?
Mniej więcej wszystko tak ma. "Normalne" typy zmiennoprzecinkowe (normalne, czyli
float, double, zapisywane w stałej ilości bitów) odwzorowują liczby z jakąśtam
dokładnością. Podczas operacji prawie zawsze wprowadza się jakąś odchyłkę.
Porównywanie takich liczb na równość lub różność to źródło smrodu. Twój fix jest ok,
to zdrowa praktyka na porównanie liczb zmiennoprzecinkowych: if abs(x-y)<0.00...001
then...
WP
-
5. Data: 2019-06-12 14:48:08
Temat: Re: Porównywanie liczb, double float
Od: Zbych <a...@o...pl>
W dniu 12.06.2019 o 14:17, Pszemol pisze:
> Dlaczego konwersja CDbl stringu 31 lub 32.8 dodaje jakieś
> śmieci do zmiennej double float na 15 miejscu po przecinku??
Bo typy rzeczywiste mają dużą dynamikę kosztem dużego szumu :-)
-
6. Data: 2019-06-12 14:56:57
Temat: Re: Porównywanie liczb, double float
Od: "Irek.N." <t...@j...taki.jest>
> Bo typy rzeczywiste mają dużą dynamikę kosztem dużego szumu :-)
Kurde, a ja myślałem, że to jitter.
Chociaż nie, jitter jest losowy, a tutaj mamy całkowitą powtarzalność,
coś jak problem z kwantami bardziej ;)
Miłego.
Irek.N.
-
7. Data: 2019-06-12 15:21:31
Temat: Re: Porównywanie liczb, double float
Od: JDX <j...@o...pl>
On 2019-06-12 14:17, Pszemol wrote:
[...]
> Pisząc w Visual Basic 6 gostek porównywał rezultat konwersji CDbl()
No nieźle, nieźle. Myślałem, że to ja jestem dinozaurem, który w chacie
używa WinXP, a tu widzę, że ludzie jeszcze komercyjnie piszą coś nowego
pod VB6, do którego extended support skończył się w 2008. :-D Tak mnie
jakoś tknął ten VB6, bo pamiętam, jak mój koleżka się nim zachwycał
gdzieś pod koniec lat 90-tych. :-D
-
8. Data: 2019-06-12 16:52:25
Temat: Re: Porównywanie liczb, double float
Od: Szyk Cech <s...@s...pl>
> Przyczyną błędu była różnica odejmowania wynosząca 15.1234e-15
>
> Dlaczego konwersja CDbl stringu 31 lub 32.8 dodaje jakieś
> śmieci do zmiennej double float na 15 miejscu po przecinku??
> A może odejmowanie stałej 1.8 wprowadza ten błąd?
>
> Czy to jest normalne zachowanie się VB6?
>
> Czy inne Visuale jak VC++ lub VC# też tak mają?
Weź chłopie ić na studia (ja miałem to nawet na wieczorowych 20 lat
temu) i się doucz! Zamiast zadawać głupie pytania. Choć gdybyś dłubał w
czymś innym niż VB to byś wiedział o problemie (w każdej książce do
Asemblera czy C czy C++ to powinno być).
-
9. Data: 2019-06-12 16:53:05
Temat: Re: Porównywanie liczb, double float
Od: q...@t...no1 (Queequeg)
In pl.misc.elektronika Mateusz Viste <m...@n...pamietam> wrote:
> Prawdziwi programiści nie używają liczb zmiennoprzecinkowych.
Nie szedłbym tak daleko. Oczywiście używają ale wiedzą też, jakie są ich
ograniczenia i jak je porównywać.
--
Eksperymentalnie: http://facebook.com/groups/pl.misc.elektronika
-
10. Data: 2019-06-12 16:54:15
Temat: Re: Porównywanie liczb, double float
Od: Cezary Grądys <c...@w...onet.pl>
W dniu 12.06.2019 o 14:29, Mateusz Viste pisze:
>
> Prawdziwi programiści nie używają liczb zmiennoprzecinkowych.
>
> Obowiązkowa lektura na wieczór:
> http://perso.ens-lyon.fr/jean-michel.muller/goldberg
.pdf
>
Nie ma co przesadzać, liczby zmiennoprzecinkowe po to powstały, żeby je
używać. Trzeba tylko porównywać je zakładając pewną dopuszczalną
tolerancję.
--
Cezary Grądys
c...@w...onet.pl