Thread View: pl.comp.os.linux.programowanie
10 messages
10 total messages
Started by Piotr Woszczynski
Thu, 09 Sep 1999 05:32
perl - banalny problem?
Author: Piotr Woszczynski
Date: Thu, 09 Sep 1999 05:32
Date: Thu, 09 Sep 1999 05:32
44 lines
2135 bytes
2135 bytes
Hej!
Ostatnimi czasy natchnelo mnie do nauki perla (tak na poczatek). Jezyk
wydaje mi sie w miare prosty i przejrzysty, z olbrzymimi mozliwosciami,
ale... No wlasnie.
Napisalem cos takiego:
#! /usr/bin/perl
$dx=0.01;
$nx=950;
while ($nx < 1000){
$nx += $dx;
print "nowe nx=$nx\n";
}
Prawda ze banal?
Uruchomilem... i zbaranialem. Otoz w pewnym momencie programik zaczal
wypluwac wyniki typu (tak troche z pamieci bo pisze ten post z windy):
nowe nx=960.0599998898
nowe nx=960.0699998898
itd.
Zaznaczam ze dla wartosci $dx calkowitych ta przypadlosc nie zachodzi,
dla mniejszej liczby iteracji tez nie.
Domyslam sie ze pewnie na wysokosci 1E-7 (powiedzmy) "zamiata" jakies
smieci z pamieci, co powoduje przy odpowiedniej liczbie iteracji
propagacje bledu i wyniki sa takie jakie sa. W jaki sposob mozna to
obejsc (czy w ogole jest na to jakis sposob)? Zaczalem podejrzewac ze
moze procek jest nieco padniety i wprowadza przeklamania, ale tez nie,
sprawdzalem na 2 roznych kompach i wyniki mniej wiecej te same. Z reszta
parokrotnie na obu kompach przekompilowywalem jadro linuxa i calos jakos
chodzi...
Probowalem byc takze "chytry" w ten sposob ze podawalem (nieco na
lopatologicznie)
$dx=0.0100000000000000000000000000000000000000000000000
i ten sam wynik. Pewnie ze mozna uznac ze jest to przyblizenie, ale tak
wygenerowane liczby maja mi sluzyc do porownywania z wartosciami
wprowadzonymi, a w tym przypadku perl staje sie bardzo konsekwentny i
wcale nie uwaza ze (w zasadzie slusznie) ze wartosc np. 960.06 =
960.0599998898
Any idea?
Piotr
Re: perl - banalny problem?
Author: Miroslaw Kwasniak
Date: Thu, 09 Sep 1999 09:44
Date: Thu, 09 Sep 1999 09:44
60 lines
3031 bytes
3031 bytes
Piotr Woszczynski <woszcz@icso.com.pl> wrote:
PW>Hej!
PW>Ostatnimi czasy natchnelo mnie do nauki perla (tak na poczatek). Jezyk
PW>wydaje mi sie w miare prosty i przejrzysty, z olbrzymimi mozliwosciami,
PW>ale... No wlasnie.
PW>Napisalem cos takiego:
PW>#! /usr/bin/perl
PW>$dx=0.01;
PW>$nx=950;
PW>while ($nx < 1000){
PW> $nx += $dx;
PW> print "nowe nx=$nx\n";
PW>}
PW>Prawda ze banal?
PW>Uruchomilem... i zbaranialem. Otoz w pewnym momencie programik zaczal
PW>wypluwac wyniki typu (tak troche z pamieci bo pisze ten post z windy):
PW>nowe nx=960.0599998898
PW>nowe nx=960.0699998898
PW>itd.
PW>Zaznaczam ze dla wartosci $dx calkowitych ta przypadlosc nie zachodzi,
PW>dla mniejszej liczby iteracji tez nie.
PW>Domyslam sie ze pewnie na wysokosci 1E-7 (powiedzmy) "zamiata" jakies
PW>smieci z pamieci, co powoduje przy odpowiedniej liczbie iteracji
PW>propagacje bledu i wyniki sa takie jakie sa. W jaki sposob mozna to
PW>obejsc (czy w ogole jest na to jakis sposob)? Zaczalem podejrzewac ze
PW>moze procek jest nieco padniety i wprowadza przeklamania, ale tez nie,
PW>sprawdzalem na 2 roznych kompach i wyniki mniej wiecej te same. Z reszta
PW>parokrotnie na obu kompach przekompilowywalem jadro linuxa i calos jakos
PW>chodzi...
PW>Probowalem byc takze "chytry" w ten sposob ze podawalem (nieco na
PW>lopatologicznie)
PW>$dx=0.0100000000000000000000000000000000000000000000000
PW>i ten sam wynik. Pewnie ze mozna uznac ze jest to przyblizenie, ale tak
PW>wygenerowane liczby maja mi sluzyc do porownywania z wartosciami
PW>wprowadzonymi, a w tym przypadku perl staje sie bardzo konsekwentny i
PW>wcale nie uwaza ze (w zasadzie slusznie) ze wartosc np. 960.06 =
PW>960.0599998898
PW>Any idea?
Wszystko w porządku (polecam dowolną literaturę na temat obliczeń
zmienno-przecinkowych). Tak zachowuje się nie tylko perl, ale i każdy inny
(normalny) język programowania operujący na typach zmiennoprzecinkowych.
W twoim przypadku jako krytermium porównania należy przyjąć warunek
(zapisany w języku abstrakcyjnym, gdyż nie znam perla):
abs( x1 - x2 ) <= eps
albo lepiej (ogólniej)
abs( x1 - x2 ) <= eps * max( abs(x1), abs(x2) )
gdzie eps zależy od gwarantowanej dokładności reprezentacji
zmiennoprzecinkowej.
Mirek
Re: perl - banalny problem?
Author: Bartosz Jakubski
Date: Thu, 09 Sep 1999 10:43
Date: Thu, 09 Sep 1999 10:43
30 lines
1265 bytes
1265 bytes
Piotr Woszczynski napisał(a):
[...]
>
>#! /usr/bin/perl
>
>$dx=0.01;
>$nx=950;
>
>while ($nx < 1000){
> $nx += $dx;
> print "nowe nx=$nx\n";
>}
>
>Prawda ze banal?
>Uruchomilem... i zbaranialem. Otoz w pewnym momencie programik zaczal
>wypluwac wyniki typu (tak troche z pamieci bo pisze ten post z windy):
>nowe nx=960.0599998898
>nowe nx=960.0699998898
>itd.
RTFM! :-)
man perlfaq4
perldoc perlfaq4
--
-- *Bartosz Jakubski* _Sosnowiec_ --
-- Free software is a matter of liberty, not price. --
-- http://www.fsf.org/philosophy --
Re: perl - banalny problem?
Author: Piotr Woszczynski
Date: Mon, 13 Sep 1999 05:49
Date: Mon, 13 Sep 1999 05:49
52 lines
3288 bytes
3288 bytes
Bartosz Jakubski napisał:
>
> Piotr Woszczynski napisał(a):
^^^ - hmmm!!!??? :-))
>
> [...]
> >itd.
> RTFM! :-)
> man perlfaq4
> perldoc perlfaq4
Dzięki za podpowied :-)
Tylko ze ten tego wychodzi ze perl nie radzi sobie z liczbami
zmiennoprzecinkowymi (a w kazdym razie to ja sobie nie radze...).
Obszedlem ten problem baaaaardzo lopatologicznie. Warosci ulamkowe
przemnozylem przez odpowiednia liczbe (10, 100, 1000 itp) tak by
otrzymac liczbe calkowita. Natrafilem na nastepna bariere...
W czym rzecz? Wymyslilem sobie programik ktory zamienialby trójki liczb
x, y, z na tablicę (macierz) tak skonstruowanš by wspolrzedne x i y
zamienione zostaly na odpowiedni nr. wiersza i kolumny, na przecięciu
których wpisywana bylaby wartosc z, w "puste" miejsca wprowadzana
wartosc "0". Dane wejsciowe zacišgane sš z pliku, w którym definiowany
jest też rozmiar macierzy poprzez wartosc minimalnš i maxymalnš x, y,
najmniejszš podziałkę na osiach x i y. Jak sš ułamkowe to przemnażane sš
przez odpowiedni mnożnik i zapisywane do pliku tymczasowego - po to by
się pozbyć liczb zmiennoprzecinkowych (bardzo to nieleganckie, ale
cóż..). Następnie otwierany jest plik temp, inicjowana tablica @t na
podstawie min, max x i y oraz dx i dy, do której na wstępie wprowadzone
sš wartosci 0. Następnie wyszukiwane sš nr wiersza i kolumny, na
podstawie których jest wyliczany indeks dla z-ta w tablicy @t i
przypisywana wartosc $t[$index]=$z[$i]. Cala tablica wprowadzana jest do
pliku w ten sposob, ze jak osiagnieta jest maxymalna wartosc liczby
kolumn (wczesniej wyliczona) wstawiany jest "\n" i leci następny wiersz.
Byłoby wszystko OK, bo to działa, tylko jedno mnie niepokoi ze w trakcie
samego zapisu odpalony proces potrafi w pamięci (obserwowany pod top-em)
urosnšc do 200MB i wywalic sie z braku pamięci (mam przy starcie procesu
~70MB wolnego RAM-u i ~100MB wolnego swapu), czy jest mozliwe jakies
odchudzenie tego procesu? Czemu sam zapis do raz otwartego pliku jest
taki pamięciożerny? Zaznaczam ze "przejsciowe" tablice i zmienne po
wykorzystaniu traktuję instrukcjš undef, tak ze w końcu istnieje
(powinna istnieć) tylko jedna tablica (nie powiem ze mała ok. miliona
$t[$i]), którš własnie zapisuję do pliku. Przy parametrach
"podprogowych" tzn jak się jeszcze miesci w pamięci otrzymuje raptem
2-3MB danych w pliku końcowym...
Co jest powodem wzrostu objętosci? Sorry za pewnie dosyć naiwne pytanie,
ale przekopałem cała ksišżkę "Programowanie w Perlu" L.Walla i psińco
nic nie wydedukowałem.
Pozdrawiam
Piotr
Re: perl - banalny problem?
Author: Marcin 'Qrczak' Kowalczyk
Date: Mon, 13 Sep 1999 11:24
Date: Mon, 13 Sep 1999 11:24
12 lines
1505 bytes
1505 bytes
Mon, 13 Sep 1999 07:49:32 +0200, Piotr Woszczynski <woszcz@icso.com.pl> pisze:
> Tylko ze ten tego wychodzi ze perl nie radzi sobie z liczbami
> zmiennoprzecinkowymi (a w kazdym razie to ja sobie nie radze...).
Nie tyle perl, co komputery - przeczytaj dokładnie to perlfaq4.
--
__("< Marcin Kowalczyk * qrczak@knm.org.pl http://kki.net.pl/qrczak/
\__/ GCS/M d- s+:-- a22 C+++>+++$ UL++>++++$ P+++ L++>++++$ E-
^^ W++ N+++ o? K? w(---) O? M- V? PS-- PE++ Y? PGP->+ t
QRCZAK 5? X- R tv-- b+>++ DI D- G+ e>++++ h! r--%>++ y-
Re: perl - banalny problem?
Author: Piotr Woszczynski
Date: Mon, 13 Sep 1999 13:35
Date: Mon, 13 Sep 1999 13:35
24 lines
1857 bytes
1857 bytes
Marcin 'Qrczak' Kowalczyk napisał: > > Mon, 13 Sep 1999 07:49:32 +0200, Piotr Woszczynski <woszcz@icso.com.pl> pisze: > > > Tylko ze ten tego wychodzi ze perl nie radzi sobie z liczbami > > zmiennoprzecinkowymi (a w kazdym razie to ja sobie nie radze...). > > Nie tyle perl, co komputery - przeczytaj dokładnie to perlfaq4. > No i przeczytalem (2 raz). Komputery sš winne. A fakt pozostaje faktem. Mogę co najwyżej otrzymac ładnie sformatowany string np. 25.95 a nie 25.9499995689 używajšc printf. Porównywać wartosci sie nie da i basta cytat ale z man perlop (do którego odesłał mnie perlfaq4 : "Testing for exact quality of floating-point equality or inequality is not a good idea(...)" Próbowałem używać Math::BigFloat, ale no cóż, chyba na razie cieńki jestem. W pętlach to mi nie wychodzi - gubione sš wartosci i wywala komunikat cos kole tego: Used noninitialize value at line ... in Math::BigFloat (jesli dobrze pamiętam). Więc na takiego cieniaża jak ja (póki co ;-) pozostajš siłowe rozwišzania (opisane w poprzednim poscie). Tylko żebym jeszcze wiedział co z tš pamięciš... Piotr
Re: perl - banalny problem?
Author: Piotr Woszczynski
Date: Mon, 13 Sep 1999 13:35
Date: Mon, 13 Sep 1999 13:35
24 lines
1857 bytes
1857 bytes
Marcin 'Qrczak' Kowalczyk napisał: > > Mon, 13 Sep 1999 07:49:32 +0200, Piotr Woszczynski <woszcz@icso.com.pl> pisze: > > > Tylko ze ten tego wychodzi ze perl nie radzi sobie z liczbami > > zmiennoprzecinkowymi (a w kazdym razie to ja sobie nie radze...). > > Nie tyle perl, co komputery - przeczytaj dokładnie to perlfaq4. > No i przeczytalem (2 raz). Komputery sš winne. A fakt pozostaje faktem. Mogę co najwyżej otrzymac ładnie sformatowany string np. 25.95 a nie 25.9499995689 używajšc printf. Porównywać wartosci sie nie da i basta cytat ale z man perlop (do którego odesłał mnie perlfaq4 : "Testing for exact quality of floating-point equality or inequality is not a good idea(...)" Próbowałem używać Math::BigFloat, ale no cóż, chyba na razie cieńki jestem. W pętlach to mi nie wychodzi - gubione sš wartosci i wywala komunikat cos kole tego: Used noninitialize value at line ... in Math::BigFloat (jesli dobrze pamiętam). Więc na takiego cieniaża jak ja (póki co ;-) pozostajš siłowe rozwišzania (opisane w poprzednim poscie). Tylko żebym jeszcze wiedział co z tš pamięciš... Piotr
Re: perl - banalny problem?
Author: Marcin 'Qrczak' Kowalczyk
Date: Mon, 13 Sep 1999 15:28
Date: Mon, 13 Sep 1999 15:28
14 lines
1542 bytes
1542 bytes
Mon, 13 Sep 1999 15:35:33 +0200, Piotr Woszczynski <woszcz@icso.com.pl> pisze:
[...]
> Porównywać wartosci sie nie da i basta
Praktycznie można, tyle że trzeba umiejętnie: np. jeśli zmienna
rośnie co 0.01, to porównujemy ją z 24.955, tzn. z wartością
w połowie przedziału.
--
__("< Marcin Kowalczyk * qrczak@knm.org.pl http://kki.net.pl/qrczak/
\__/ GCS/M d- s+:-- a22 C+++>+++$ UL++>++++$ P+++ L++>++++$ E-
^^ W++ N+++ o? K? w(---) O? M- V? PS-- PE++ Y? PGP->+ t
QRCZAK 5? X- R tv-- b+>++ DI D- G+ e>++++ h! r--%>++ y-
Re: perl - banalny problem?
Author: Piotr Woszczynski
Date: Tue, 14 Sep 1999 10:07
Date: Tue, 14 Sep 1999 10:07
22 lines
1386 bytes
1386 bytes
Miroslaw Kwasniak napisał: > > Wszystko w porzšdku (polecam dowolnš literaturę na temat obliczeń > zmienno-przecinkowych). Tak zachowuje się nie tylko perl, ale i każdy inny > (normalny) język programowania operujšcy na typach zmiennoprzecinkowych. > W twoim przypadku jako krytermium porównania należy przyjšć warunek > (zapisany w języku abstrakcyjnym, gdyż nie znam perla): > > abs( x1 - x2 ) <= eps > > albo lepiej (ogólniej) > > abs( x1 - x2 ) <= eps * max( abs(x1), abs(x2) ) > > gdzie eps zależy od gwarantowanej dokładnoci reprezentacji > zmiennoprzecinkowej. Długo mi zajęło przetrawienie tego co napisałes ;-), ale wypróbuję, kiepskie to nie jest (chyba..).Dzięki za podpowied. :-) Piotr
Re: perl - banalny problem? -rozwiazanie
Author: Piotr Woszczynski
Date: Wed, 15 Sep 1999 04:51
Date: Wed, 15 Sep 1999 04:51
33 lines
1654 bytes
1654 bytes
Idiotyczne odpowiadać sobie na zadane pytanie - nie, nie- wszystko z
mojš głowš jest OK! :-))
Muszę się pochwalić że znalazłem rozwišzanie. Otóż po każdej iteracji
należy użyć funkcji pack i unpack:
stary kod:
> #! /usr/bin/perl
>
> $dx=0.01;
> $nx=950;
>
> while ($nx < 1000){
> $nx += $dx;
# tu dopisać
$nxx=pack "p", $nx; # <-----
$nx=unpack "p", $nxx; # <-----
> print "nowe nx=$nx\n";
> }
i działa !!! Tzn. wyniki otrzymywane sš z przyzwoitš precyzjš: otrzymuję
w końcu moje upragnione przykładowe 979.02 a nie 979.019999988. Pewnie
dla niektórych jest to sprawa oczywista ale skoro nie ma tego w perlfaq4
(polecany mi do poduszki), to pomyslałem że warto się pochwalić. A nuż
(i widelec) ktos bedzie mial podobne "rozterki". Wadš tego rozwišzania
jest to że program wyranie zwalnia, ale pewnie tak musi być...
Pozdrawiam
Piotr
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads