[solved] Python - niezrozumiałe działanie porównania zmiennych

Bash, C, C++, Java, PHP, Ruby, GTK, Qt i wiele innych - wszystko tutaj.
outslider
Sędziwy Jeż
Sędziwy Jeż
Posty: 68
Rejestracja: 03 lis 2007, 23:14
Płeć: Mężczyzna
Wersja Ubuntu: 11.04
Środowisko graficzne: GNOME
Architektura: x86_64
Kontakt:

[solved] Python - niezrozumiałe działanie porównania zmiennych

Post autor: outslider »

Witam!

Problem jest z kodem tak banalnym, że nie wiem, jak to może nie działać... kod:

Kod: Zaznacz cały

YMIN=-2.0
YMAX=2.0
d=30
y=YMIN
while y <= YMAX:
    print y
    y=y+(YMAX-YMIN)/(d-1)
wynik jest taki:

Kod: Zaznacz cały

-2.0
-1.86206896552
-1.72413793103
-1.58620689655
-1.44827586207
-1.31034482759
-1.1724137931
-1.03448275862
-0.896551724138
-0.758620689655
-0.620689655172
-0.48275862069
-0.344827586207
-0.206896551724
-0.0689655172414
0.0689655172414
0.206896551724
0.344827586207
0.48275862069
0.620689655172
0.758620689655
0.896551724138
1.03448275862
1.1724137931
1.31034482759
1.44827586207
1.58620689655
1.72413793103
1.86206896552
mimo iż spodziewam się raczej:

Kod: Zaznacz cały

-2.0
-1.86206896552
-1.72413793103
-1.58620689655
-1.44827586207
-1.31034482759
-1.1724137931
-1.03448275862
-0.896551724138
-0.758620689655
-0.620689655172
-0.48275862069
-0.344827586207
-0.206896551724
-0.0689655172414
0.0689655172414
0.206896551724
0.344827586207
0.48275862069
0.620689655172
0.758620689655
0.896551724138
1.03448275862
1.1724137931
1.31034482759
1.44827586207
1.58620689655
1.72413793103
1.86206896552
2.0
czyli z wartością "2.0" na końcu...

Kiedy zmienię kod na:

Kod: Zaznacz cały

YMIN=-2.0
YMAX=2.0
d=30
y=YMIN
while y <= YMAX+0.0000000001:
    print y
    y=y+(YMAX-YMIN)/(d-1)
to jakimś cudem otrzymuję to "2.0" na końcu. I to nie "2.0000000001" tylko właśnie "2.0". Kiedy zmienię d=30 na d=31 albo d=29 albo praktycznie na cokolwiek, to już działa, a dla 30 czy 60 nie. Dla d=3 też działa. Czy jest to jakaś kwestia przybliżeń? Czy co...

Nie mogę zastosować tego +0.0000000001 ponieważ wartości YMIN i YMAX oraz d mogą być bardzo zmienne i może się okazać, że są wręcz porównywalne z 0.0000000001 a wtedy kod się też będzie sypać...

Generalnie ciężka bania...
Wielki powrót do Ubuntu - jestem mile zaskoczony!
Awatar użytkownika
karmelek
Przyjaciel
Przyjaciel
Posty: 883
Rejestracja: 10 lut 2007, 17:45
Płeć: Mężczyzna
Wersja Ubuntu: 11.04
Środowisko graficzne: GNOME
Architektura: x86
Kontakt:

Odp: Python - niezrozumiałe działanie porównania zmiennych

Post autor: karmelek »

Faktycznie - może to być kwestia przybliżeń. Przynajmniej u mnie przy podobnych problemach winny okazywał się sposób reprezentacji liczb w komputerze.
Wszystkich moderatorów Bóg po śmierci zabiera do nieba, żeby ci dwadzieścia cztery godziny na dobę moderowali modlitwy do niego.
http://karmelek.wordpress.com
inny OS=debian lenny
outslider
Sędziwy Jeż
Sędziwy Jeż
Posty: 68
Rejestracja: 03 lis 2007, 23:14
Płeć: Mężczyzna
Wersja Ubuntu: 11.04
Środowisko graficzne: GNOME
Architektura: x86_64
Kontakt:

Odp: Python - niezrozumiałe działanie porównania zmiennych

Post autor: outslider »

To kiepsko... Masz jakąś metodę, żeby to obejść?
Wielki powrót do Ubuntu - jestem mile zaskoczony!
VGT
Piegowaty Guziec
Piegowaty Guziec
Posty: 21
Rejestracja: 20 lut 2011, 21:47
Płeć: Mężczyzna
Wersja Ubuntu: 10.10
Środowisko graficzne: GNOME
Architektura: x86
Lokalizacja: Iława
Kontakt:

Odp: Python - niezrozumiałe działanie porównania zmiennych

Post autor: VGT »

Na początek: kod niestety w innym języku, ale nie koduję w Pythonie, więc nie chciałem w ciemno pisać, bo mogłoby wyjść gorzej ;) Mam nadzieje, że kod z Javy będzie na tyle przejrzysty, że wyjaśni koncepcję:

Kod: Zaznacz cały

		float yMin = -2.0f;
		float yMax = 2.0f;
		float yStartValue = yMin;
		int d= 30;
		float y = yStartValue;
		int step = 0;
		while (y <= yMax)
			{
			++step;
			System.out.println(y);
			y = yStartValue + step * ((yMax - yMin) / (d - 1));
			}
Zastosowane tu jest coś podobnego, co powszechnie jest stosowane w transformacjach geometrii w grafice 3D. Jeśli miałeś kiedyś okazję coś takiego pisać, gdybyś próbował w każdej kolejnej klatce np obracać jakiś model 3D, z czasem zaczyna on być zniekształcony właśnie z powodu zaokrągleń. Rozwiązanie, to trzymać współrzędne modelu cały czas w bazowej formie, a w każdej kolejnej klatce nadawać mu coraz większy obrót, jednak nie nadpisywać tym bazowego modelu, a użyć jedynie do jego wyświetlenia.

Tak samo tutaj. W pętli za każdym razem do y przypisuję jego wartość początkową (co prawda tutaj akurat jest to yMin, ale zawsze wolę mieć osobną zmienną przechowującą wartość startową dla przejrzystości, stąd utworzenie yStartValue) powiększoną o ilość iteracji (wartość step) zmian, które chce do y dodać.

W Javie po takiej modyfikacji udało się 2.0 uzyskać. Jednak tak czy inaczej w przypadku zmiennych float/double ryzykowne jest oczekiwanie, że dwie wartości będą sobie równe właśnie ze względu na zaokrąglenia.
Try not. Do or do not... There is no try
outslider
Sędziwy Jeż
Sędziwy Jeż
Posty: 68
Rejestracja: 03 lis 2007, 23:14
Płeć: Mężczyzna
Wersja Ubuntu: 11.04
Środowisko graficzne: GNOME
Architektura: x86_64
Kontakt:

Odp: Python - niezrozumiałe działanie porównania zmiennych

Post autor: outslider »

@VGT
Dzięki! Działa!
W ogóle dopiero jak implementowałem Twój algorytm zauważyłem, że przecież ja robię tyle przebiegów co d+1 czyli mogę inkrementować spokojnie zmienną step dla step<=d :D Wtedy w ogóle nie ma problemu przybliżeń.

Pozdrawiam!
Wielki powrót do Ubuntu - jestem mile zaskoczony!
ODPOWIEDZ

Wróć do „Programowanie”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 12 gości