Hallo, ich habe folgendes Problem. Für eine Geschwindigkeitserkennung benötige ich einen Timer welcher teil einer Berechnung ist. hier z.B. die Formel: N = 3000000 / T_N_PLS oder VS = DIST * 90000 / T_VS_PLS normal wären die Zahlen noch größer aber ich habe im Vorfeld den Ausdruck schon so weit wie möglich gekürzt. N und VS sind jeweils unsigned int oder int zahlen, d.h. N (Drhezahl) bewegt sich zwischen 0 und 10000 U/min VS hingegen ist eine Geschwindigkeit in Km/h also auch locker in ein unsigned char unter zu bringen. Jetzt die Frage, wie wird der C Compiler (CodeVision AVR in meinem Fall) die Berechnung durchführen? Bei erster Berechnung z.B.? Wenn N ein unsigned int ist, passt da ja die 3000000 niemals rein, T_N_PLS ist aber technisch immer so bedingt das das Ergebnis der Rechnung immer in ein unsigned int passen muss. Bekomme ich da Probleme bei diesen beiden Berechnungen oder muss ich die Ausgabevariable dann evtl. in ein unsigned long oder double speichern um ausreichend platz zu haben? Gruß Malte.
Du kannst ja "(long) long int", bzw int32_t (oder (u)int64_t, beide in <stdint.h>) verwenden (und ein L an feste Zahlen anhängen). oder du machts die Berechnung z.B. in Umdrehungen/sekunde, bzw. m/s hth. Jörg
Malte S. wrote: > Hallo, > > Jetzt die Frage, wie wird der C Compiler (CodeVision AVR in meinem Fall) > die Berechnung durchführen? > > Bei erster Berechnung z.B.? Wenn N ein unsigned int ist, passt da ja die > 3000000 niemals rein, T_N_PLS ist aber technisch immer so bedingt das > das Ergebnis der Rechnung immer in ein unsigned int passen muss. Bekomme > ich da Probleme bei diesen beiden Berechnungen oder muss ich die > Ausgabevariable dann evtl. in ein unsigned long oder double speichern um > ausreichend platz zu haben? Du musst zunächst mal die linke Seite einer Zuweisung von der rechten Seite trennen. Beide haben nur bedingt miteinander zu tun. Der Compiler macht * Zuerst die Berechnung * dann wird das Ergebnis der Berechnung so angepasst, dass es in die Ergebnisvariable links passt (falls das notwendig ist) * dann erfolgt die Zuweisung. Insbesondere ist wichtig: Welchen Datentyp N hat, ist für die Berechnung von 3000000 / T_N_PLS völlig unwichtig. Für die Berechnung selbst sind nur die Datentypen der beteilgten Operanden interessant, welchen Datentyp die Ergebnisvariable hat, ist zu diesem Zeitpunkt völlig uninteressant. 3000000 / T_N_PLS 3000000 hat welchen Datentyp? Der Compiler versucht es zunächst mal mit int, bemerkt aber, dass ein int zu klein ist um so eine Zahl aufzunehmen und weist daher dieser Zahl den Datentyp long zu. Allerdings empfiehlt es sich bei solchen Dingen explizit zu sein. Schreibe besser 3000000L, dann weist du selber auch, dass das ein long ist. T_N_PLS musst du selber wissen, was das ist. -> die Division wird zumindest im Datentyp long ausgeführt (wenn T_N_PLS ein unsigned long ist, dann wird 3000000 zu unsigned long umgeformt), und das Ergebnis ist dann ebenfalls ein long. Damit kommt der Compiler zu Schritt 2: Wie passen linke und rechte Seite vom Datentyp her zusammen? links steht ein int, rechts steht ein long. Ergo muss der Compiler irgendetwas damit machen. Er tut dies, indem die höherwertigen Bytes des long berworfen werden und nur soviele Bytes übrig bleiben, wie in einen int passen. Es ist dein Problem als Programmierer, dafür Sorge zu tragen, dass da nichts schief geht. Laut eigener Aussage sind die Werte aber immer so, dass das Ergebnis in einen int passen wird. Daher passiert da nichts wenn ... ... Schritt 3 ausgeführt wird: die eigentliche Zuweisung. Was ist mit der anderen Berechnung? VS = DIST * 90000 / T_VS_PLS Wieder: lass uns das Augenmerk zunächst mal nur auf die rechte Seite richten. Da steht DIST * 90000 / T_VS_PLS Welches ist der Datentyp von DIST, welches ist der Datentyp von 90000. Nun, von DIST weis ich es nicht, aber von 90000. 90000 ist ein int (der Compiler probiert bei ganzen Zahlen immer zuerst einen int und nur wenn die Zahl da nicht hineinpassen würde, kriegt die Zahl den Datentyp long). DIST * 90000 Dieser Ausdruck hat das Potential überzulaufen. Ob das passieren kann, kannst nur du wissen, das hängt von den Werten in DIST ab. Falls DIST ein int ist, und du Gefahr eines Überlaufs läufst, dann ist es klug, diese Berechnung im Zahlenraum long ausführen zu lassen. Wieder: Die Berechnung findet in dem Datentyp statt, der der 'größere' der beiden Operanden ist. DIST lass ich mal in Ruhe, dafür zwinge ich den Compiler aus den 90000 einen long zu machen: 90000L und damit wird auch diese Multiplikation in long ausgeführt. Zwischenergebnis / T_VS_PLS Da das Zwischenergebnis ein long ist, wirdauch die Division im Datentyp long ausgeführt und das Ergebnis ist wieder ein long. Schritt 2: Passen die Datentypen links und rechts? Rechts steht ein long, links ein unsigned char. Wiederrum ist es dein Problem dafür zu Sorgen, dass das Ergebnis vom Wertebereich her in einen unsigned char passt. Dem Compiler ist das wurscht, der lässt einfach die überzähligen Bytes unter den Tisch fallen, wenn er ... Schritt 3: ... die Zuweisung ausführt.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.