[C++] Zufallszahlen generieren

BodyLove

Commodore
Registriert
Apr. 2003
Beiträge
4.481
tja,

ich bin gerade an einem Programm, welches ein Spiel darstellen soll. Wer anfängt, entscheidet der Zufall. In diesem Fall sind es max. 2 Spieler, also müsste es 0 oder 1 sein.

anfangs habe ich,

Code:
#include<iostream.h>
#include<math.h>
#include<time.h>
void main()
srand ((unsigned)time(NULL))
{
	int anzahlmuenzen, spieleranzahlmuenzen, k, j, spielertaktik,computeranzahlmuenzen, computergezogen, spielergezogen;
	spieleranzahlmuenzen=0;
	computeranzahlmuenzen=0;
	cout<<"Bitte geben sie die Anzahl der Muenzen ein."<<endl;
	cin>>anzahlmuenzen;
	do
	{
		for( k=0;anzahlmuenzen>=0:k=k+1)
		{
			if (k%2==0)
			{
				int (computergezogen=rand()%3);
			}
			if (k%2==1)
			{
			int spielergezogen=rand%3;
			}
			anzahlmuenzen=anzahlmuenzen-(spielergezogen+computergezogen);
			
			spieleranzahlmuenzen=spieleranzahlmuenzen+spielergezogen;
			computeranzahlmuenzen=computeranzahlmuenzen+computergezogen;
			computergezogen=0;
			spielergezogen=0;
		}
	}while (anzahlmuenzen>7);

	do
	{
		for(j=k;anzahlmuenzen>=0;j=j+1)
		{
			if (k%2==0)
			{	
				int computergezogen=rand%3;
				anzahlmuenzen=anzahlmuenzen-computergezogen;
				computergezogen=0;
			}
			else
			{
					if(3>=anzahlmuenzen-4)
					{
						spielertaktik=anzahlmuenzen-4;
						spielergezogen=spielertaktik;
						anzahlmuenzen=anzahlmuenzen-spielergezogen;
						spielergezogen=0;
						spielertaktik=0;
					};
			}
		}	
	}while(anzahlmuenzen=0);			
				

}

Tja, aber irgendwie will er es nicht so ganz. Das Programm ist noch nicht fertig, aber sollte auch so zumindest lauffähig sein.

ach ja, das ist seit geraumer Zeit wieder mal mein erster Versuch mit C++ zu programmieren. Habt bitte nachsicht. Ich würde gerne nur die srandfunktion zum laufen kriegen. Für den Rest muss ich mich weiterhin sorgen.;)

Gruß Body

edit: Stimmt die srand funktion? Normalerweise braucht man dafür doch nur die time.h.
 
Zuletzt bearbeitet:
Hab grad keinen C-Compiler zur Hand, sber was für nen Fehlermeldung bekommst due denn? Der Code wirkt auf mich etwas ... ähem ... unübersichtlich.
 
Ist klar.:)

Übersichtlichkeit ist eh etwas, was ich nicht beherrsche (noch;)).

Die Fehlermeldungen bekomme ich beim srand ((unsigned)time(NULL)). "Unexpectet end of file" und ein "synthax error, missing ';' before srand."

kannst du kurz ein bsp mit srand posten?
 
Das was du da schreibst erinnert nur sehr entfernt an C / C++.

ich hab auch keinen C++ compiler zur hand aber so wär meine Vorstellung von C++ Code mit srand()

Code:
#include<iostream.h>
#include<math.h>
#include<time.h>
[color=red]void main()
{
	srand(time(0));[/color]
        int anzahlmuenzen, spieleranzahlmuenzen, k, j, spielertaktik,computeranzahlmuenzen, computergezogen, spielergezogen;
	spieleranzahlmuenzen=0;
	computeranzahlmuenzen=0;
	cout<<"Bitte geben sie die Anzahl der Muenzen ein."<<endl;
	cin>>anzahlmuenzen;
	do
	{
		for( k=0;anzahlmuenzen>=0[color=red];[/color]k=k+1)
		{
			if (k%2==0)
			{
				[color=red]computergezogen=rand()%3;[/color]
			}
			if (k%2==1)
			{
			        int spielergezogen=rand%3;
			}
			anzahlmuenzen=anzahlmuenzen-(spielergezogen+computergezogen);
			
			spieleranzahlmuenzen=spieleranzahlmuenzen+spielergezogen;
			computeranzahlmuenzen=computeranzahlmuenzen+computergezogen;
			computergezogen=0;
			spielergezogen=0;
		}
	}while (anzahlmuenzen>7);

	do
	{
		for(j=k;anzahlmuenzen>=0;j=j+1) // optional ginge auch j++ anstatt j = j + 1
		{
			if (k%2==0)

			{	
				int computergezogen=rand%3;
				anzahlmuenzen=anzahlmuenzen-computergezogen;
				computergezogen=0;
			}
			else
			{
					if(3>=anzahlmuenzen-4)
					{
						spielertaktik=anzahlmuenzen-4;
						spielergezogen=spielertaktik;
						anzahlmuenzen=anzahlmuenzen-spielergezogen;
						spielergezogen=0;
						spielertaktik=0;
					};
			}
		}	
	}while(anzahlmuenzen=[color=red]=[/color]0); // Keine Zuweisungen in der Bedingung, die sind immer true!
				

}
Ansonsten schließe ich ein paar Klammerfehler nicht aus, wie gesagt hab das nicht kompiliert.
Zur Übersichtlichkeit: Gewöhn dir bei Zuweisungen Leerstellen zwischen den Operatoren an.
Code:
int zahl = 3; // oder
int andereZahl= 12;
int dritteZahl = zahl % andereZahl;
Das dürfte schonmal viel zur Übersichtlichkeit beitragen.
 
Zuletzt bearbeitet:
Okay, zumindest ist es übersichtlicher geworden.:)

Aber der Fehler bleibt trotzdem. Naja, egal. Muss morgen dann halt doch zur Übung. Viel dank für die Mühen. :)
 
IMO kommt die Fehlermeldung von dieser Konstruktion.
PHP:
void main()
srand ((unsigned)time(NULL))
{


Probier das mal aus, so sollte das generieren von 0 und 1 per Zufall klappen.

PHP:
#include <iostream.h>
#include <time.h>

int main()
{
      char quit = '\0';
      srand( (unsigned)time(NULL));

      while (quit != 'q')
      {
          cout << "Null oder Eins : " << rand()%2 << endl;
          cin >> quit;
      }
}
 
Werde ich machen. Bin aber bis jetzt mit dem Programm relativ zufrieden. Abgesehen davon, dass es nicht läuft.

Imho liegt es nur am srand. Irgendwas scheine ich vergessen zu haben. Der Professor weiß bestimmt einen Rat. :)
 
Lösung des Problems ist ganz einfach ;) srand ist in stdlib.h definiert.
Außerdem ist die Verwendung der "alten" C-Header unschön. Lass das .h weg und schreib ein c davor. Aus stdlib.h wird dann z.B. cstdlib. Genauso unschön ist das Inkludieren von C++-Headern, die auf .h enden. Lass das .h weg und schreib dafür using namespace std;

Außerdem, jeder moderne Compiler meckert bei void main (). Nur int main () und int main (int argn, char* argv[]) sind portabel. Dann aber am Schluss nie das return 0; vergessen.

So, genug gemeckert :) (Nimms Dir nicht so zu Herzen *g*)

Mal ganz nebenbei, was studierst Du? =)

Code:
#include <iostream>
#include <ctime>
#include <cstdlib>

using namespace std;

int main ()
{
  char quit = '\0';
  srand( (unsigned)time(NULL));

  while (quit != 'q')
  {
    cout << "Null oder Eins : " << rand()%2 << endl;
    cin >> quit;
  }
  return 0;
}
 
Zuletzt bearbeitet:
@7H3 N4C3R
Aha, sehr schön erklärt. Ich nutze C zwar kaum, ist mir für den Hausgebrauch zu aufwändig, ist aber sehr nützlich es zumindest lesen zu können. Da kommen deine Erläuterungen zum modernen C gerade recht.
Ich war schon der Meinung der Compiler vom DevCpp braucht ein Update, da er sich erdreistete mein 'void main(void)' zu kritisieren ;) Meine Kentnisse zu C sind wohl doch schon stärker angestaubt als ich dachte.

Lösung des Problems ist ganz einfach srand ist in stdlib.h definiert.
Das es bei mir auch ohne stdlib ging muß dann wohl daran liegen das die stdlib von einem der beiden anderen includes includiert wurde?
 
Naja das mit den Headern ist C++-Spezifisch. Hatte ich geschrieben, weil das Topic [C++] sagte...

Wenn du nur mit C arbeitest, bleibt es natürlich bei stdlib.h etc. .

Laut diversen Manpages ist srand in stdlib.h definiert. Wenn es bei Dir hinzugekommen ist.. hmm muss durch ein anderes include passiert sein. Darauf sollte man sich aber nie verlassen.
 
hi,

danke erstmal für die Hilfe.:)

Ich habe mal ein weiteres Programm hergestellt, nur wollte der Prof es mit Funktionen...

Undzwar den hier:
Code:
#include<iostream.h>
void main()
{

	double amEndedesJahres,amAnfangdesJahres, zinsen, einzahlbetrag, auszahlbetrag, laufzeit;
	cout<<"Bitte geben sie den Einzahlbetrag ein.";
	cin>>einzahlbetrag;
	cout<<"Bitte geben sie den Auszahlbetrag ein.";
	cin>>auszahlbetrag;
	cout<<"Bitteg geben sie die Laufzeit ein.";
	cin>>laufzeit;

	amAnfangdesJahres=0;
	for(double i=0.00001;amEndedesJahres<=auszahlbetrag;i=i+0.00001)
	{
		
		amAnfangdesJahres=0;
		amEndedesJahres=0;
		zinsen=0;
		
		for(double k=1;k<=laufzeit;k=k+1)
		{
		amAnfangdesJahres=einzahlbetrag+amEndedesJahres;
		zinsen=amAnfangdesJahres*i;//2100
		amEndedesJahres=zinsen+amAnfangdesJahres;//2100+21000
		cout<<k<<endl;
		};
	};
	cout<<i;
};

Nun habe ich das mit Funktionen versucht,
Code:
#include<iostream.h>
//using namespace std;

berechnen(double fEinzahlbetrag,double fAuszahlbetrag,double fLaufzeit)
{
	double amAnfangdesJahres, amEndedesJahres, zinsen; //zinssatz;
	amAnfangdesJahres=0;
	for(double i=0.00001;amEndedesJahres<=fAuszahlbetrag;i=i+0.00001)
	{
		
		cout<<i;//Dieses cout steht nur zur Kontrolle da, und es gibt auch den richtigen Wert wieder.
		amAnfangdesJahres=0;
		amEndedesJahres=0;
		zinsen=0;
		
		for(double k=1;k<=fLaufzeit;k=k+1)
		{
		amAnfangdesJahres=fEinzahlbetrag+amEndedesJahres;
		zinsen=amAnfangdesJahres*i;//2100
		amEndedesJahres=zinsen+amAnfangdesJahres;//2100+21000
		//cout<<k<<endl;
		};
	};
	//cout<<i;
	return i;
};

void main()
{

	double einzahlbetrag, auszahlbetrag, laufzeit,i;
	cout<<"Bitte geben sie den Einzahlbetrag ein.";
	cin>>einzahlbetrag;
	cout<<"Bitte geben sie den Auszahlbetrag ein.";
	cin>>auszahlbetrag;
	cout<<"Bitteg geben sie die Laufzeit ein.";
	cin>>laufzeit;
	i=berechnen(einzahlbetrag, auszahlbetrag, laufzeit);

	cout<<"Ihr Zinssatz betraegt: "<<i<<endl;
}

Der funktioniert zwar, aber beim return i wird statt 0,725xxx, 0 wiedergegeben. Ich habe mal ein cout in die ForSchleife geschrieben, um nachzusehen, ob es überhaupt berechnet wird, und siehe da, i steigt bis auf 0,725xx hoch. Aber return i, gibt das falsche wieder. Ist beim Aufbau was verkehrt?

ist in:
Code:
 void main()

i=berechnen(einzahlbetrag, auszahlbetrag, laufzeit);
was falsch?

Danke im Voraus. Gruß Body

Das andere läuft nun. Zwar war der Prof erstaunt, dass es überhaupt lief, aber es lief.:)
 
Alsoooo :) Das Programm hat mehrere Probleme. Auch wenn mir das Verhalten gerade noch nicht ganz offensichtlich ist.. (ich gehe erstmal davon aus, dass das der Rückgabewert der Funktion berechne durch copy'n'paste verloren gegangen ist :))

for (double i; ....) ...

Nach dem C++98 Standard ist i danach nicht mehr definiert. Seine Sichtbarkeit (Scope) erstreckt sich über die Schleife. Entweder hast Du noch irgendwo ein anderes i global deklariert, oder was der Compiler hier macht ist reine Nettigkeit. Definiere double i = 0 vor dem for, das ist schonmal korrekter. (Lass mir raten... Borland C++ 3.1? :) )

for(double i=0.00001;amEndedesJahres<=auszahlbetrag;i=i+0.00001)

Was diese Schleife so in ihrem Verlauf machen wird, ist sehr ungewiss. Das liegt daran, dass es für 0.00001 sehr wahrscheinlich keine exakte binäre Repräsentation gibt (Habe das jetzt nicht geprüft). Das heißt: je länger diese Schleife läuft, desto stärker wird die Ungenauigkeit dabei.

Grundsätzlich sollte man doubles als Schleifenvariablen vermeiden. Lass einen int laufen und teile ihn dann jeweils durch 100000. Geschwindigkeitsmäßig wird das so gut wie garnichts ausmachen. Denk daran, den int vor dem Teilen aber in einen double zu casten, sonst werden alle Nachkommastellen weggeschmissen.


Ist mir grad noch aufgefallen:
amEndedesJahres ist bei der for-Schleife noch undefiniert. Kleine Grundsatzregel: Jede Variable, die man definiert, initialisiert man immer. Das hilft sehr, Fehler zu vermeiden. Gute Compiler hätten Dir dort aber auch zumindest eine Warning geliefert.
 
Zuletzt bearbeitet:
Hi 7H3 N4C3R und vander,

das mit dem möglichen Verlust wird vom Compiler auch gewarnt, nur ist dies laut Prof, nicht so dramatisch, da die Zahlen sich nicht zu viele Stellen hinterm Komma haben.

ich habe zwar die Problematik verstanden, aber mir ist kein Weg bewusst, wie man das in den Griff bekommen könnte. Im Skript wird leider zu der Thematik nichts gesagt.:(

Ich habe jetzt aus i Zinssatz gemacht, da dies nachvollziehbarer ist.

Der code läuft wie gesagt, richtig durch. Nur beim Return Zinssatz; übergibt er halt anscheinend einen falschen Wert. Ich habe nur vor der ersten For-Schleife den Zinssatz mit 0 definiert. Hilft aber in diesem Fall nicht weiter.

Sehr komisch das ganze. Wenn alles schief geht, gebe ich bei der Abgabe meinen alten Code.

Danke an euch alle.:)

Code:
#include<iostream.h>
//using namespace std;

berechnen(double fEinzahlbetrag,double fAuszahlbetrag,double fLaufzeit)
{
	[b]double[/b] amAnfangdesJahres, amEndedesJahres, zinsen, [b]zinssatz=0[/b];
	amAnfangdesJahres=0;
	for([b]zinssatz=0.00001[/b];amEndedesJahres<=fAuszahlbetrag;[b]zinssatz=zinssatz+0.00001[/b])
	{
		
		//cout<<zinssatz;//Dieses cout steht nur zur Kontrolle da, und es gibt auch den richtigen Wert wieder.
		amAnfangdesJahres=0;
		amEndedesJahres=0;
		zinsen=0;
		
		for(double k=1;k<=fLaufzeit;k=k+1)
		{
		amAnfangdesJahres=fEinzahlbetrag+amEndedesJahres;
		zinsen=amAnfangdesJahres*[b]zinssatz[/b];//2100
		amEndedesJahres=zinsen+amAnfangdesJahres;//2100+21000
		//cout<<k<<endl;
		};
	};
	cout<<zinssatz<<endl;
	[b]return zinssatz;[/b]
};

void main()
{

	[b]double[/b] einzahlbetrag, auszahlbetrag, laufzeit, [b]zinssatz[/b];
	cout<<"Bitte geben sie den Einzahlbetrag ein.";
	cin>>einzahlbetrag;
	cout<<"Bitte geben sie den Auszahlbetrag ein.";
	cin>>auszahlbetrag;
	cout<<"Bitteg geben sie die Laufzeit ein.";
	cin>>laufzeit;
	[b]zinssatz=berechnen(einzahlbetrag, auszahlbetrag, laufzeit);[/b]
	cout<<"Ihr Zinssatz betraegt: "<<[b]zinssatz[/b]<<endl;
}
 
Zuletzt bearbeitet:
Ist es vielleicht das:

Code:
#include<iostream.h>
//using namespace std;

[color=red]double[/color] berechnen(double fEinzahlbetrag,double fAuszahlbetrag,double fLaufzeit)
{
	[b]double[/b] amAnfangdesJahres=0, amEndedesJahres=0, zinsen, [b]zinssatz=0[/b];
	for([b]zinssatz=0.00001[/b];amEndedesJahres<=fAuszahlbetrag;[b]zinssatz=zinssatz+0.00001[/b])
	{
		
		//cout<<zinssatz;//Dieses cout steht nur zur Kontrolle da, und es gibt auch den richtigen Wert wieder.
		amAnfangdesJahres=0;
		amEndedesJahres=0;
		zinsen=0;
		
		for(double k=1;k<=fLaufzeit;k=k+1)
		{
		amAnfangdesJahres=fEinzahlbetrag+amEndedesJahres;
		zinsen=amAnfangdesJahres*[b]zinssatz[/b];//2100
		amEndedesJahres=zinsen+amAnfangdesJahres;//2100+21000
		//cout<<k<<endl;
		};
	};
	cout<<zinssatz<<endl;
	[b]return zinssatz;[/b]
};

void main()
{

	[b]double[/b] einzahlbetrag, auszahlbetrag, laufzeit, [b]zinssatz[/b];
	cout<<"Bitte geben sie den Einzahlbetrag ein.";
	cin>>einzahlbetrag;
	cout<<"Bitte geben sie den Auszahlbetrag ein.";
	cin>>auszahlbetrag;
	cout<<"Bitteg geben sie die Laufzeit ein.";
	cin>>laufzeit;
	[b]zinssatz=berechnen(einzahlbetrag, auszahlbetrag, laufzeit);[/b]
	cout<<"Ihr Zinssatz betraegt: "<<[b]zinssatz[/b]<<endl;
}

Hast Du jetzt schon zwei mal hintereinander so gepostet :-) Frage mich, warum es ohne überhaupt kompiliert. Habe es gerade mal getestet.
 
Nein, hatte kleine Modifikationen durchgenommen. Aber im großen und ganzen war es nahezu identisch.:)

Du wirst lachen, aber im Skript wird dies mit nichten erwähnt. Kannst du mir sagen, warum ich das double hier

Code:
double berechnen(double fEinzahlbetrag,double fAuszahlbetrag,double fLaufzeit)
anzuwenden brauch. Wie gesagt, ich will ungern denselben Fehler 2mal begehen.:)

Danke, es funktioniert jetzt, wie es sein sollte.
 
Das gibt an, war für einen Wertetyp die Funktion zurückgibt (also wenn du return xxxx schreibst). Ich wundere mich sehr, warum das ohne dem auch kompiliert, hätte eigentlich nicht sein dürfen.
 
Zurück
Oben