🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.programming
Article #215631

Re: Porównywanie liczb, double float

#215631
From: bartekltg
Date: Thu, 13 Jun 2019 21:25
93 lines
4707 bytes
On Wednesday, June 12, 2019 at 3:07:25 PM UTC+2, bartekltg wrote:
> On Wednesday, June 12, 2019 at 2:17:44 PM UTC+2, Pszemol wrote:
> > 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 :-)
> 
> Ale nie działasz na liczbach rzeczywistych, ale na reprezentacji
> zmiennoprzecinkowej. 
> Wszytkie trzy liczby tak naprawde mają wartość tylko zblizoną
> do tych napisanych. 
> 
> > 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.
> 
> Używaj funkcji abs, to samo, a czytelniej. 
> 
> Tak, to jest poprawne rozwiązanie. 
> 
> > 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ą?
> 
> W sumei to pierwsz rzecz, jakiej człowiek sie dowiaduja na jakimkolwiek
> poważniejsyzm kursie dotykającym zmiennego przecinka. Ze szczegolnym
> uwzlgędnieniem
> "Nie wykonuj porównania == i <> na liczbach zmiennoprzecinkowych"
> 
> 
> A jaka przyczyna? To przy okazji opisują.
> 
> Zerknij na wiki, jak wyglada liczba zmiennoprzecinkowa.
> 
> 2^coś *1.mantysa.
> 
> 1/2 tak zapiszesz, ale 1/3 nie. 1/10 też nie.
> Zerknij tutaj, 
> https://www.h-schmidt.net/FloatConverter/IEEE754.html 
> Liczy na single, ale zasada ta sama.
> wpisując 1.8 tak naprawdę trzymasz najbliższa
> reprezentaowalną liczbę, 1.7999999523162841796875
> Podobnie 32.8. 
> 31 jest reprezentowane dokładnie. 
> 
> Teraz każda podstawowa operacja arytmetyczna biorąca argumenty
> a i b (oznaczamy fl(a) i fl(b) jako wartośći reprezentowane) liczy 
> fl(a) (działanie) fl(b) dokładnie, a potem zapisuje jako najbliższa
> reprezentowalna wartość. 
 
> W ogolności 
> fl(a+b) = (fl(a)+fl(b))(1+eps), gdize ten epsylon to dokłądność
> reprezentacji. 

Lepiej by było, jakbym napisał, że eps jest rzędu wielkośći reprezentacji.
Może być 0, może być jak dokładność v, dodatnia lub ujemna. Wzorkiem:
abs( eps ) < v.




 pzdr
 bartekltg
Technical Details
Message-ID: <13b53e34-add7-4c9a-a754-611296d76fea@googlegroups.com>
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!newsfeed.pionier.net.pl!takemy.news.telefonica.de!telefonica.de!weretis.net!feeder7.news.weretis.net!proxad.net!feeder1-2.proxad.net!209.85.160.216.MISMATCH!j96no128988qte.0!news-out.google.com!33ni31qtt.0!nntp.google.com!j96no128985qte.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail
References: <qdqqh6$n2f$1@dont-email.me> <a843c978-5bcc-4a8a-97bd-67b77c7defe7@googlegroups.com>

Show Full Headers
Complete Article Headers
X-Received: by 2002:ac8:19d8:: with SMTP id s24mr77719738qtk.44.1560461119120;        Thu, 13 Jun 2019 14:25:19 -0700 (PDT)
X-Received: by 2002:a05:620a:1519:: with SMTP id i25mr40955389qkk.331.1560461118832; Thu, 13 Jun 2019 14:25:18 -0700 (PDT)
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!newsfeed.pionier.net.pl!takemy.news.telefonica.de!telefonica.de!weretis.net!feeder7.news.weretis.net!proxad.net!feeder1-2.proxad.net!209.85.160.216.MISMATCH!j96no128988qte.0!news-out.google.com!33ni31qtt.0!nntp.google.com!j96no128985qte.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail
Newsgroups: pl.comp.programming
Date: Thu, 13 Jun 2019 14:25:18 -0700 (PDT)
In-Reply-To: <a843c978-5bcc-4a8a-97bd-67b77c7defe7@googlegroups.com>
Complaints-To: groups-abuse@google.com
Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=80.54.0.14; posting-account=CvUQzQoAAABvVQmR58QmR6N4Cev1qhAS
NNTP-Posting-Host: 80.54.0.14
References: <qdqqh6$n2f$1@dont-email.me> <a843c978-5bcc-4a8a-97bd-67b77c7defe7@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <13b53e34-add7-4c9a-a754-611296d76fea@googlegroups.com>
Subject: Re: Porównywanie liczb, double float
From: bartekltg <bartekltg@gmail.com>
Injection-Date: Thu, 13 Jun 2019 21:25:19 +0000
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit