Pow fehler - manchmal 10^2 = 99

Hallo alle zusammen,
ich habe hier ein Problem, das ich nicht lösen kann.
Habe ein Jump & Run Spiel mit Allegro geschrieben. Dafür habe ich dann (erstmal) extra (als eigene Datei/eigenes Projekt) ein Programm zum laden von Levels geschrieben. Ich habe das Programm mal etwas vereinfacht und verallgemeinert. Die Level Datein sehen so aus:

A 0000 0000
B 0001 0000

Das erste Zeichen steht für die Nummer des Tiles o.ä. dann kommt die X-Koordinate, wobei es genau vier Zeichen sein müssen (bei beispielsweise 123 wird vorne noch eine 0 angehängt - also 0123. Bei 12 zwei nullen: 0012 usw.

Hier ist das Programmm:

#include 
#include 
#include 
#include 

using namespace std;

int main (int argc, char \*\*argv[])
{
 fstream f;
 f.open("level0.lvl", ios::in);
 if (f)
 {
 const int ziffern=4;
 char line[64];
 while (!f.eof())
 {
 f.getline(line, sizeof(line));
 char tile=line[0];
 int x=0;
 int y=0;
 char fehler=0;
 for (int i=0; i57) || (line[i+ziffern+3]57)) {
 }
 else {
 x+=(line[i+2]-48)\*(int)pow(10, ziffern-i-1);
 y+=(line[i+ziffern+3]-48)\*(int)pow(10, ziffern-i-1);
 }
 }
 cout 


Nun habe ich aber das Problem, dass beim 2. For-Schleifen-Durchlauf (also i=1) die Ziffer in der Datei mit 99 multipliziert wird. Wenn ich einfach so pow(10,2) benutze klappt auch alles. Nach mehrstündigem herumprobieren habe bin ich dann zu dem Schluss gekommen, dass irgendein Zeichen im Quelltest stehen muss, das nicht angezeigt wird (s. ASCII-Tabelle).
Also habe ich das ganze Programm per Hand abgeschrieben. Aber wieder geb es den selben Fehler. Woran kann das liegen?
Wenn ich nur in einer For-Schleife alle Potenzen abfrage, funktioniert alles, aber wenn ich das dann zu meinem (jetztigem) Programm erweitere, dann gibt es diesen Fehler. Und wenn ich in meine Programm noch 

    cout in die For-Schleife schreibe wird sogar 99 angezeigt.
    Dann habe ich mal einen großen Teil aus dem Programm entfernt (alles was mit dem Laden der Datei usw zu tun hat) und das Programm die Ergebnise von 10 hoch i (0 bis 10) anzeigen lassen, und es gab teatsächlich Fehler bei manchen Potenzen. Auch bei der Basis von 5, aber nicht von 2!
    
    
    Jetzt weiß ich nicht mehr weiter. Ich habe bei google gesucht, aber nichts gefunden. Ich benutze MinGW und CodeBlocks, aber wenn das Problem beim Compiler oder bei der Entwicklungsumgebung liegen würde, wäre ich bei meiner Suche wahrscheinlich schon auf Ergebnisse gestoßen.
    
    Nun weiß ich nicht mehr weiter. Ich hoffe ihr könnt mir helfen oder zur Lösung beitragen.
    Ansonsten werde ich das irgendwie anders machen, aber es wäre schon selsam, wenn es da nicht eine logische Lösung gäbe.
    
    
    Viele Grüße, Max

x+=(line[i+2]-48)*(int)pow(10,ziffern-i-1);
Und wenn ich in meine Programm noch

cout in die For-Schleife schreibe wird
sogar 99 angezeigt.

Hallo,

pow arbeitet mit doubles, evt. kommt als Ergebnis 99.9999999999 heraus, welches durch „(int)“ auf 99 abgerundet wird.

Als Trick: Vor dem Aufrunden 0.5 hinzuaddieren.

Sicherer ist es allerdings, nur mit ints zu rechnen.
also mit 1000 anfangen
und dann immer durch 10 teilen.

Eine weitere Variante ist die Folgende:

x += 1. Ziffer
x *= 10;
x += 2. Ziffer
x *= 10;

Viel Erfolg
Thorsten

P.S.: Zum ausprobieren:

float f = 0;
for(int i=0; i
Welche Zahl wird ausgeben? Es ist nicht die 42 :wink:

super idee, aber du hast das power cycling nicht bedacht, deswegen den reward unterhalb der neanderschwelle setzen

gruss
matt

pow arbeitet mit doubles, evt. kommt als Ergebnis
99.9999999999 heraus, welches durch „(int)“ auf 99 abgerundet
wird.

Als Trick: Vor dem Aufrunden 0.5 hinzuaddieren.

Das klingt einleuchtend, sowas habe ich mir auch schon überlegt, selsam ist dann aber, das

cout 
100 augibt.



> Sicherer ist es allerdings, nur mit ints zu rechnen.  
> also mit 1000 anfangen  
> und dann immer durch 10 teilen.  
>   
> Eine weitere Variante ist die Folgende:  
>   
> x += 1. Ziffer  
> x \*= 10;  
> x += 2. Ziffer  
> x \*= 10;  
> ...


Ja, daran habe ich noch nicht gedacht! Von der Rechenzeit her ist es wahrscheinlich sogar ein bischen schneller.

Danke für die Antwort, Max

super idee, aber du hast das power cycling nicht bedacht,
deswegen den reward unterhalb der neanderschwelle setzen

Kennst Du bestimmt schon … Extra für Dich gemacht:
http://video.google.de/videoplay?docid=7639498508899…

Hallo.
Du hast noch nen anderen kleinen Fehler.

int main (int argc, char **argv[])

Hier hast du bei argv ein Sternchen bzw. die Klammern zuviel.

 int main (int argc, char \*\*argv) 

oder

 int main (int argc, char \*argv[]) 

Alex

Hi Max,

nun mal eine Antwort von einem praktischen Informatiker, da die Antworten vom theoretischen Informatiker nur partiell richtig bzw. nicht vollständig waren und diese weiter unten ja auch zu einem „off-topic“ Streit führten.

Punkt 1: Ja, float und doubles sind ungenau. Aber: Sowohl die 10.0, als auch die 100.0 haben eine exakte Darstellung im IEEE 754, denn 10=8+2, 100=64+32+4 IEEE754= (weiteres dazu unter http://de.wikipedia.org/wiki/IEEE_754).

Punkt 2: Ich gehe davon aus, dass du fälschlicherweise die -1 hinter der pow Klammer stehen hattest, also ‚*((pow(10,2)-1)‘

Punkt 3: Will man nur int Varianten von pow10, so definiert man in der Regel eine eigene int Funktion, die 10^n ausrechnet. Diese ist um einen sehr grossen Faktor schneller als die double pow Funktion.

Punkt 4: Bei so einfachen Eingabeformaten kann man durchaus die streams Funktionalitäten von C++ verwenden und dann muss man weder die eine noch die andere pow Funktion benutzen, sondern bekommt das Ganze mehr oder weniger geschenkt:

 if (f)
 {
 do 
 {
 char c = 0;
 int x\_off = 0;
 int y\_off = 0;
 if (f \>\> c \>\> x\_off \>\> y\_off)
 {
 printf("-\>%c %d %d\n",c, x\_off, y\_off);
 }
 else
 {
 printf("Condition eof=%d bad=%d fail=%d\n",f.eof(),f.bad(),f.fail());
 }
 } while (!f.eof());
 }

Gruss
norsemanna

kriegst du wohl öfters zu sehen, das video

Punkt 2: Ich gehe davon aus, dass du fälschlicherweise die -1
hinter der pow Klammer stehen hattest, also ‚*((pow(10,2)-1)‘

Nein, daran liegt es nicht.

Punkt 3: Will man nur int Varianten von pow10, so definiert
man in der Regel eine eigene int Funktion, die 10^n
ausrechnet. Diese ist um einen sehr grossen Faktor schneller
als die double pow Funktion.

Ja, ich habe es jetzt ja auch anders gemacht.

Punkt 4: Bei so einfachen Eingabeformaten kann man durchaus
die streams Funktionalitäten von C++ verwenden und dann muss
man weder die eine noch die andere pow Funktion benutzen,
sondern bekommt das Ganze mehr oder weniger geschenkt:

Naja, in dem Fall schon, aber ich habe schon geschrieben, das ich das eigentlich dafür verwenden will, um ein Level zu laden und anzuzeigen. Das heißt, ich brauche die Koordinaten nacher als int und nicht als string in der Konsole.

Das Problem habe ich (bzw. mehr oder weniger ich, da ich McGee’s Variante etwas verändert benutze) ja nun auch gelöst. Trotzdem danke für deine Antwort,
max

Hi,

Punkt 4: Bei so einfachen Eingabeformaten kann man durchaus
die streams Funktionalitäten von C++ verwenden und dann muss
man weder die eine noch die andere pow Funktion benutzen,
sondern bekommt das Ganze mehr oder weniger geschenkt:

Naja, in dem Fall schon, aber ich habe schon geschrieben, das
ich das eigentlich dafür verwenden will, um ein Level zu laden
und anzuzeigen. Das heißt, ich brauche die Koordinaten nacher
als int und nicht als string in der Konsole.

bitte lies doch die Antworten vollstaendig, ich habe von „streams“ geredet, nicht von strings. Es werden in meinem Beispiel sehr wohl chars und ints eingelesen.

Gruss
norsemanna