🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

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?
#223
Author: Piotr Woszczynski
Date: Thu, 09 Sep 1999 05:32
44 lines
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?
#224
Author: Miroslaw Kwasniak
Date: Thu, 09 Sep 1999 09:44
60 lines
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?
#226
Author: Bartosz Jakubski
Date: Thu, 09 Sep 1999 10:43
30 lines
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?
#227
Author: Piotr Woszczynski
Date: Mon, 13 Sep 1999 05:49
52 lines
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?
#228
Author: Marcin 'Qrczak' Kowalczyk
Date: Mon, 13 Sep 1999 11:24
12 lines
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?
#229
Author: Piotr Woszczynski
Date: Mon, 13 Sep 1999 13:35
24 lines
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?
#232
Author: Piotr Woszczynski
Date: Mon, 13 Sep 1999 13:35
24 lines
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?
#230
Author: Marcin 'Qrczak' Kowalczyk
Date: Mon, 13 Sep 1999 15:28
14 lines
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?
#225
Author: Piotr Woszczynski
Date: Tue, 14 Sep 1999 10:07
22 lines
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ładnoœci 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
#233
Author: Piotr Woszczynski
Date: Wed, 15 Sep 1999 04:51
33 lines
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 wyraŸnie 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