PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Rechenproblem (Syntax?)



Bääääär
18.02.2008, 21:31
Hallo.

Ich habe hier einigen Code, der ein anderes Ergebnis auspuckt, als mir logisch erscheint. Ich vermute ein Syntaxproblem, da ich noch nicht allzulange mit C arbeite:

#define MinValue 0
#define MaxValue 1024
...
uint16_t val11,val12,val21,val22,resval1 = 0,resval2 = 0;
char result;
...
result = (char)(((resval2-MinValue)*128)/MaxValue);

wenn resval2 512 ist, kommt Null raus, obwohl 64 rauskommen sollte.

Vielleicht kann mir jemand auf die Sprünge helfen.
Danke,
Bääääär

Steinigtmich
18.02.2008, 22:28
Ja, das liegt an dem uint16_t. Der ist zu klein.
512*128=65536 (Hex wäre das 0x10000). uint16_t kann nur bis 65535 (0xFFFF, also 2 Byte = 16 Bit, daher uint16). Also Überauf, er fängt dann wieder bei 0 an. Und 0/1024 ist 0.

Edit: Lange Erklärung, kurzer Sinn... nimm nen uint32_t, dann passts wieder.

Bääääär
19.02.2008, 17:50
Joh, stimmt, das war's. Ich hatte das ganze auch schon andersherum (erst dividieren, dann multiplizieren) aber da hat der Compiler wahrscheinlich ein und dasselbe draus gemacht.

Danke, jetzt weiß ich zumindest beim nächsten Mal, wo ich den Fehler suchen kann ^^

Bääääär

rudirabbit
06.03.2008, 19:29
Will jetzt keinen neuen Thread erstellen, da ich ein ähnliches Problem wie
Bääääär habe.

void Int7print(void)
{
uint32_t hi_time,low_time;


hi_time = (high_pulse *64);
low_time = (low_pulse *64);


itoa(high_pulse,Portt,10);
Printat(0,2,Portt);

itoa(low_pulse,Portt,10);
Printat(7,2,Portt);

double freqq = (1 / (hi_time + low_time)) *1000000;


dtostrf(freqq,4,2,Portt);
Printat(12,2,Portt);

int7=false;


Dort sollte eine aus den Timer Werten (vom ext INT7 die Frequenz berechnet werden.
Habe einen ext. Funktionsgenator an INT 7 PIN.
Die angezeigten Timer Werte (Low/High) sind plausibel.

Als Frequenz wird mir aber immer 0.00 angezeigt ? warum ?
Printat(x,y,wert) schreibt ins LCD

Bin ein Umsteiger von Pascal auf C ;-)

Gruß

KayH
06.03.2008, 20:41
Hi,

hi_time und low_time sind Integer. Du fuehrst eine Division mit Integern durch (1/Integer). Dabei kommt immer 0 raus. Erst am Ende wird diese Integer-0 in eine Double-0 umgewandelt ...
Du musst entweder die 1 oder das Ergebnis deiner Addition zuerst in einen Float/Double Wert umwandeln. Diese Art Fehler wurde hier schon mehrfach angesprochen.
Wenn Dir diese Aussage allein nicht weiterhilft, kannst Du ja noch etwas hier suchen. Du wirst bestimmt fuendig. ;-) Zusaetzlich sind da noch viel mehr Erklaerungen zu finden.

hth
Kay

Ceos
07.03.2008, 09:42
ich möchte hier ma anmerken was ich mit dem GCC erlebt habe, gut möglich das ihr damit auch manchmal probleme habt

uint32_t hi_time,low_time;


nachdem ich jede variable EINZELN deklariert habe (also nicht durch komma getrennt) haben sich bei unserem kleinen asuro-projekt urplötzlich ALLE undefinierten verhalten in wohlgefallen aufgelöst!

lorcan
07.03.2008, 12:11
Versuch es doch mal mit einem sogenannten Cast, das heißt du nimmst die Integer-Werte und wandelst sie vor der Berechnung in Double-Werte um. Das geschieht durch das "double" in Klammern.

Und ganzzahlige Konstanten, die Fließkommazahlen bzw. Double-Werte enthalten immer mit nem ".0" abschließen, sonst sind es Integer-Werte.

Und wie schon gesagt die Deklarationen für Variablen immer an den Anfang der Funktion, der GCC mag das nicht so gerne und das ist auch übersichtlicher.



void Int7print(void)
{
uint32_t hi_time,low_time;
double freqq;

hi_time = (high_pulse *64);
low_time = (low_pulse *64);


itoa(high_pulse,Portt,10);
Printat(0,2,Portt);

itoa(low_pulse,Portt,10);
Printat(7,2,Portt);

freqq = (1.0 / ((double) hi_time + (double) low_time)) * 1000000.0;


Gruß Lorcan

Ceos
07.03.2008, 12:35
vorsicht mit dem casten, die variable wird dann nur INTERPRETIERT aber wenn du mit einer gecasteten variable rechnest, wird ihr speicher dadurch NICHT größer!!! aber auf double zu casten hilft ungemein wenn du die nachkommastellen mitnehmen willst ...



((double) hi_time + (double) low_time) schmeckt mir iwie nicht, da kommt am ende was undefiniertes bei raus möchte ich meinen ... evtl. die ganze klammer nochmal casten.
aber ob da nicht signifikante bits unter den tisch fallen ??? notfalls die berechnung vorher in einer echten double zwischenspeichern und dann mit dieser rechnen ... ich vertrau dem GCC nicht mehr so recht was klammern und deklarationen angeht

zerush
07.03.2008, 12:45
Sobald du das als double castest, rechnet er damit auch als double. Auch mit dem entsprechenden Platzbedarf!

Und wieso sollte da etwas undefiniertes rauskommen? Klar, wenn hi_time um einen bestimmten exponenten größer ist, fällt low_time unter den Tisch. Aber das hast du genauso, wenn du diese Variablen als double vorliegen hast...
Das liegt ganz einfach an der internen Speicherung des Datentyps.

Pro Berechnung verwendet der GCC immer den größten Datentyp der einzelnen Summanden/Multiplikatoren.

So wie Lorcan es geschrieben hat, sollte s also keine Probleme geben.

Gruß
zerush

Ceos
07.03.2008, 12:51
jut, danke für die lehrstunde, ich klopf auf holz, der gcc hat mir schon so einiges serviert, wo es keine warnings gab aber das prog total rumgesponnen hat .... liegt wohl daran das ich meine programme nicht immer wohlüberlegt schreibe sondern lieber 10min ins debuggen investiere ... blöd nur bei nem mega8 gibs kein debugging ^^ nur simulation und die geht nur bedingt ohne die hardware XD

zerush
07.03.2008, 12:59
So manch einer wunderte sich schon über folgendes:



unsigned char a;
unsigned char b;
unsigned short c;

a = 200;
b = 200;
c = b + a;


Gibt natürlich keine Fehler oder Warnings, ist ja alles korrekt.
Aber man erhält für c trotzdem 144 und nicht 400 !! ;)

Wenn der Datentyp also größer ist, in dem man hinein spiechert, muss man also mindestens einen der beiden kleineren casten.

mfg
zerush

Ceos
07.03.2008, 13:23
bei mir wars ein 10x10 array, dessen werte bei x oder y > 8 nonsens ABER > 0 ergaben worauf mein asuro fröhlich grinsend in die kreissäge gefahrn iss ^^

alle anderen werte hätten auch mist sein können, zufällig aber warnse mit 0 initialisiert deshalb sah es so aus als ob er richtig tickt

rudirabbit
07.03.2008, 17:53
Hallo

Danke für die zahlreichen Antworten.
Habe den Tip von lorcan mit dem Typcast nach Double versucht, hat auch das erwartete Ergebnis gebracht :-)

Bin wie gesagt ein Umsteiger von Pascal auf C. Bei meinem Pascompiler hätte das ohne Typcasting funktioniert, muss da ein wenig Umdenken.

Da es für den AVR leider keinen Bug Freien Pas Compiler (mikropas) gibt, bin ich auf C umgestiegen.

Finde langsam sogar Gefallen an C, nicht zuletzt deshalb wenn einem C Dau hier so gut geholfen wird O:)

Gruß Rudi