C++ nie działający if


(baton1) #1

Właśnie co z nudów uznałem że czas pobawić się w C++ (wcześniej jedynie php). Napisałem sobie w ramach ćwiczenia program rozwiązujący proste zadanie matematyczne. Wszystko było dobrze aż jeden if nie przestał mi działać (nie wiem po czym) a gapie się w ten ekran już chyba z pół godziny i nie mogę dojść o co biega. Pewnie jakieś głupstwo, no ale będę wdzięczny za wskazanie problemu. Oto kod:

#include 

using namespace std;


float till2x (float a, float b)

{

	float a1;

	a1 = a;

	while(a!=b*2)

	{

		a++;

		b++;

	}

	a = a - a1;

	return (a);

}


float ago2x (float a, float b)

{

	float a1;

	a1 = a;

	while(a!=b*2)

	{

		a--;

		b--;

	}

	a = a - a1;

	return (a);

}


int main()

{

	int y;

	cout << "Czy chcesz sprawdzic kiedy twoj ojciec byl lub bedzie dwa razy starszy od ciebie?\n1. Tak\n2. Nie\n";

	cin >> y;

	cout << endl;


	while(y==1)

	{

		float f;

		float s;


		cout << "Aby sprawdzic kiedy twoj ojciec bedzie od ciebie 2x starszy podaj jego wiek \n";

		cin >> f;

		if(f>0)

		{

			cout << endl << "Teraz podaj swoj wiek \n";

			cin >> s;


			if(s>0)

			{

				if(f/s>2)

				{

					float x;

					x = till2x(f,s);

					cout << endl << "Twoj ojciec bedzie od ciebie 2x starszy za " << x << " lat.\n";

				}

				else

				{

					float x;

					x = ago2x(f,s);

					cout << "Twoj ojciec byl od ciebie 2x starszy " << x << " lat temu.\n";

				}

				cout << endl << "Czy chcesz ponownie sprawdzic kiedy twoj ojciec byl lub bedzie dwa razy starszy od ciebie?\n1. Tak\n2. Nie\n";

				cin >> y;

			}

			else

			{

				cout << "\n\nPodales nieprawidlowe dane!";

				break;

			}

		}

		else

		{

			cout << "\n\nPodales nieprawidlowe dane!";

			break;

		}

	}


	cout << "\n\n";

	system("pause");

	return 0;

}

Nie działa mi lnijka 51 "if(f/s>2)" - niezależnie czy jest większe czy mniejsze i tak wykonuje pierwszą instrukcję.

Z góry dzięki za pomoc. :slight_smile:


(somekind) #2

U mnie działa. (Tylko musiałem wywalić jakieś dziwne system("pause") z końca, którego w ogóle nie powinno tam być.


(baton1) #3

u mnie pokazuje że powinien być za starszy za np -10 lat jak wpiszesz dla ojca 20 a dla syna 15.

system("pause") jest aby się konsola sama nie zamykała


(Tomek Matz) #4

W tym if-ie powinno być if(f/s<2.0). Weźmy te Twoje przykładowe dane, czyli 20 i 15, i otrzymamy 20/15=1,(3). Jakby nie patrzeć nie jest to liczba większa niż 2.

A odnośnie samego programu ... zastanów się co próbujesz wyliczyć. Jaki wg Ciebie powinien być wynik tego programu dla danych 20 i 15?


(baton1) #5

wstawienie 2.0 również nie działa

przy danych 20 i 15 powinno przejść do else i wykonać fukcję ago2x a następnie napisać "Twoj ojciec byl od ciebie 2x starszy 10 lat temu", a on cały czas wykonuje to tak jakby 20/15>2 i wykonuje funkcję till2x i pisze "Twoj ojciec bedzie od ciebie 2x starszy za -10 lat."


(Drobok) #6

"Twoj ojciec był od ciebie 2x starszy za -10 lat temu."

Bo jak matzu mówi, to nie wina ifa lecz twojej fukcji. Odejmujesz wszystko, a potem znów odejmujesz :stuck_out_tongue: Daj wartość bezwzględną i będzie działać :stuck_out_tongue:

btw jak ktoś może zrobić dziecko mając 5lat ? Tak samo gość może podać syna starszego niż ojca i już masz pętlę :stuck_out_tongue:


(baton1) #7

Przez przypadek przy przepisywaniu wszystkiego w ago2x zamiast a=a1-a wpisałem drugi raz a=a-a1. A całość ma logiczny sens dla ojca w wieku 50 lat a syna 30 - taka rzecz już jest normalna a odpowiedź będzie taka jak dla 20 i 15. A przed zabezpieczeniem, aby syn nie był starszy od ojca rzeczywiście nie pomyślałem :slight_smile:

Dzięki wszystkim za trud


(somekind) #8

Wiesz w ogóle, co robi ta instrukcja? Tak się tego nie robi, bo nie ma sensu uzależniać kodu takiego programu od systemu operacyjnego. Użyj po prostu cin.get().


(Tomek Matz) #9

Jeszcze raz spojrzałem na ten kod i faktycznie, masz rację. Znaku nierówności nie trzeba ruszać. Ale to 2.0 zostaw w tym if-ie, żebyś porównywał float z float-em, a nie int z int-em.


(Damgora) #10

Lepiej chyba żeby przeszedł na całkowite bo pojawienie się ułamka może sprawić problem ze skończeniem pętli:

while(a!=b*2)

   {

      a++;

      b++;

   }

A tak na marginesie jeśli zadanie/przykład nie zakłada użycia pętli to całość można łatwiej policzyć (x = f - 2 * s) :wink:


(Mad.) #11

Jeśli chcesz pozostać przy liczbach zmiennoprzecinkowych, to sprawdź je z pewną dokładnością. Przykład:

zamień

while(a!=b*2)

na

// dodaj na początku #include 

while (abs (a - b*2) < dokladnosc) // gdzie dokładność np. 0.0001

@matzu Masz rację, zapomniałem o negacji 8)

while ( !(abs (a - b*2) < 0.0001) )

(Tomek Matz) #12

@cayman3_11

Z tym problemem ze skończeniem pętli masz oczywiście rację (ten problem w sumie dość często pojawia się na forum). Skoro to się już pojawiło to podrzucę link, który moim zdaniem świetnie obrazuje o co chodzi http://blogs.msdn.com/b/kirillosenkov/archive/2009/07/20/comparing-doubles-can-produce-unexpected-results.aspx (może przyda się autorowi tematu).

@Mad.

Spoko :slight_smile: Teraz jest OK. Zamiast negacji można by też zrobić >=, ale w sumie ! bardziej pasuje do linku, który wkleiłem powyżej. Łatwiej można się zorientować o co chodzi.


(baton1) #13

To zadanie sam sobie wymyśliłem na poczekaniu, aby zrobić program który coś naprawdę robi i chciałem użyć w miarę dużo rzeczy z tych których w tutorialach się nauczyłem. Dzięki wszystkim za rady i opinie, postaram się je uwzględnić zarówno teraz (od dla treningu) jak i na pewno w przyszłości się przydadzą gdy problemy do rozwiązania będą cięższe.

Tak naprawdę w funkcjach a i b są zawsze typu int, jednak float było potrzebne aby uwzględnić w if dzielenie z częścią ułamkową - dlatego zastosowałem float, ale fakt że potem można je zmienić na int, co by uniknąć problemów.


(Tomek Matz) #14

@baton1

Jeśli na wejściu program ma zawsze otrzymywać liczby całkowite, to powinieneś już na samym początku użyć typu całkowitoliczbowego (o czym zresztą wspominał cayman3_11) do ich przechowywania. Tymczasem u Ciebie zmienne f i s są typu float (tak przy okazji ... nadawaj zmiennym nazwy mówiące o ich przeznaczeniu, czyli zamiast tego f mogłeś chociaż zrobić fAge). Owszem w tym if-ie masz dzielenie z częścią ułamkową, ale wyniku tego dzielenia przecież nigdzie nie zapamiętujesz. Mógłbyś więc zrobić rzutowanie, czyli if((float)f/s>2.0) i uzyskałbyś dokładnie to co potrzebujesz. Później te Twoje funkcje jako parametry przyjmowałyby już zmienne całkowitoliczbowe i oszczędziłbyś sobie kłopotów, o których była mowa przed chwilą (mam na myśli fragment kodu, który wrzucił Mad.). Zasada jest prosta ... o ile to możliwe unikaj typów zmiennoprzecinkowych.

I jeszcze jedno ... rozumiem, że chciałeś wykorzystać jak najwięcej elementów języka, ale przecież w programowaniu nie chodzi o to, żeby komplikować kod na siłę :slight_smile: Jak się da napisać prościej, to Twoim zadaniem jest to zrobić. Nic nie stoi na przeszkodzie, żeby sobie wymyślić kolejne zadanie, trudniejsze od tego. Jak znajdę to wrzucę Ci link do strony z zadaniami o różnym poziomie trudności.

-- Dodane 05.07.2011 (Wt) 1:23 --

http://pl.spoj.pl/problems/latwe/ - dostępne są też średnie, trudne i tzw. wyzwania; istnieje też anglojęzyczny spoj

http://main.edu.pl/pl/archive/pa

Powodzenia :slight_smile: