Forum: Compiler & IDEs cast Problem von unsigned nach signed


von Daniel (Gast)


Lesenswert?

Hallo,

ich möchte die Beschleunigung ausrechnen und habe hierzu folgende 
Variablen mit folgenden Typen:
1
int16_t ssBeschleunigung 
2
uint32_t ulGeschwindigkeitalt
3
uint32_t ulGeschwindigkeitneu
1
ssBeschleunigung = ((ulGeschwindigkeitalt-ulGeschwindigkeitneu)*100)/ulGeschwindigkeitneu);

Der Faktor 100 ist nur um Fließkommazahlen "wegzubekommen".
Nun kommt es vor, dass natürlich die neue Geschwindigkeit langsamer als 
die alte ist, d.h. es wird verzögert. Die Beschleunigung ist daher 
negativ. Ich bekomme aber auf meinem LCD immer eine positive Ausgabe. Es 
liegt an den unsigned Variablen ulGeschwindigkeitalt und 
ulGeschwindigkeitneu. Aber wie caste ich das auf ein signed, sodass die 
Berechnung noch stimmt?

Kann mir jemand helfen?

Danke.

von Programmierer (Gast)


Lesenswert?

Daniel schrieb:
> Nun kommt es vor, dass natürlich die neue Geschwindigkeit langsamer als
> die alte ist, d.h. es wird verzögert. Die Beschleunigung ist daher
> negativ.

Deshalb hast du auch das Problem, ein uint32_t fasst nunmal keine 
negativen Zahlen. Entweder du kannst auf int32_t wechseln (welcher 
Wertebereich wird verwendet), oder du musst auf int64_t umsatteln (wird 
der vom compiler/der libc unterstützt)?

von Daniel (Gast)


Lesenswert?

Ja, das ist richtig, das weiß ich soweit auch, dass es keine negative 
Zahlen fasst.
Das uint32_t wird aber nicht "voll ausgeschöpft", d.h. es ist noch Platz 
in den 32-bit, Wertebereich < 32-bit/2. Weshalb ich es in der Berechnung 
einfach casten wollte auf ein int32.

von Sam P. (Gast)


Lesenswert?

Ich weiss, die Frage klingt doof, aber... warum machst du es dann nicht 
einfach?

von J.-u. G. (juwe)


Lesenswert?

Daniel schrieb:
> Das uint32_t wird aber nicht "voll ausgeschöpft", d.h. es ist noch Platz
> in den 32-bit, Wertebereich < 32-bit/2.

Warum nimmst Du dann nicht, wie von "Programmierer" vorgeschlagen, 
gleich int32 für Deine Geschwindigkeitsvariablen?

von Klaus W. (mfgkw)


Lesenswert?

1
ssBeschleunigung = (((int32_t)ulGeschwindigkeitalt-ulGeschwindigkeitneu)*100)/ulGeschwindigkeitneu);

von Daniel (Gast)


Lesenswert?

Weil ich zuvor mit diesen Variablen eine unsigned Rechnung benötige, da 
ich diese aus einem Zeitstempel hole und die Differenz dieser 
Zeitstempel berechne. Da hier ein Überlauf auftreten kann (da der Timer 
ja durchläuft), benötige ich zuvor eine unsigned Rechnung. Erst bei der 
Beschleunigung können dann negative Werte auftreten.

Klar, ich könnte das zuvor in ein int32_t übertragen und mit diesen dann 
weiter rechnen. Ich dachte aber man könnte es einfach casten...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Daniel schrieb:

Mit einem Zwischenschritt?

Dann wird es auch besser lesbar bei den Riesenlangenvariablennamen.
1
int16_t ssBeschleunigung;
2
uint32_t ulGeschwindigkeitalt;
3
uint32_t ulGeschwindigkeitneu;
4
int32_t lGeschwindigkeitDiff;
5
6
lGeschwindigkeitDiff = ulGeschwindigkeitalt - ulGeschwindigkeitneu;
7
8
ssBeschleunigung = (lGeschwindigkeitDiff * 100) / ulGeschwindigkeitneu);
Allerdings kann es zu Überläufen kommen: Bei der Multiplikation und auch 
bei der Differenzbildung, weil die Differenz zweier n-Bit Variablen von 
-2^n bis 2^n reichen kann; die entsprechende signed-Variable aber nur 
Werte von -2^{n-1} bis 2^{n-1}-1 halten kann.

von (prx) A. K. (prx)


Lesenswert?

Klaus Wachtler schrieb:
1
> ssBeschleunigung =
2
> (((int32_t)ulGeschwindigkeitalt-ulGeschwindigkeitneu)*100)/ulGeschwindigkeitneu);
3
>

Das bringt rein garnix, weil int32 <op> uint32 => uint32.

von Rolf Magnus (Gast)


Lesenswert?

Daniel schrieb:
> Ich dachte aber man könnte es einfach casten...

Kann man:
1
ssBeschleunigung = (((int32_t)ulGeschwindigkeitalt-(int32_t)ulGeschwindigkeitneu)*100)/(int32_t)ulGeschwindigkeitneu);

Klaus Wachtler schrieb:
> ssBeschleunigung = 
(((int32_t)ulGeschwindigkeitalt-ulGeschwindigkeitneu)*100)/ulGeschwindig keitneu);

Ein einziger Cast reicht nicht. Bei einer Operation, in der signed- und 
unsigned-Operanden vorkommen, wird erstmal der signed-Operand nach 
unsigned konvertiert (also in diesem Fall dein Cast wieder rückgängig 
gemacht) und dann die Rechnung in unsigned durchgeführt.

von Klaus W. (mfgkw)


Lesenswert?

na, dann halt meinetwegen 2 casts :-)

von Rolf Magnus (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> na, dann halt meinetwegen 2 casts :-)

Einspruch: 3 Casts.

von Klaus W. (mfgkw)


Lesenswert?

der dritte ist geschenkt...

Einfacher wäre der Tip mit einem Blick in ein passendes Buch; wieso 
sollen wir immer nachsehen, wenn einer zu faul ist (ok, man könnte es 
sich auch merken, aber wenn ich es wirklich brauche schaue ich nach - 
wieso können die Frager das nicht, um ihr Problem zu lösen?).

von Daniel (Gast)


Lesenswert?

- Weil der Frager ein Anfänger ist und (noch) kein C-Buch besitzt.
- Weil der Frager dachte, dass Foren dazu da sind und es auch anerkennt, 
wenn andere Leute in ihrer Freizeit helfen
- Weil auch Dritte davon noch lernen können ;-)

Danke.

von Klaus W. (mfgkw)


Lesenswert?

Naja, aber wenn jemand jetzt für den Rest seines Lebens jedes Problem 
dieser Qualität von anderen lösen lässt, ist das etwas ineffizient.

Wenn ich wissen will, was irgendein Wort auf Englisch heißt, frage ich 
nicht in einem Forum und beschäftige damit Leute, sondern schlage halt 
da nach, wo es steht. Analog alle anderen Trivialitäten.

Sinn eines Forums ist doch eher, wirkliche Probleme zu lösen, die nicht 
eben mal durch Nachschlagen zu erledigen sind. Eher weniger, allen 
Leuten aus dem K&R oder dem Stroustrup vorzulesen, weil sie keine Lust 
haben, selbst zu lesen.

Und eben genau solche Rechenregeln stehen in einem besseren C-Buch und 
sie sind auch leicht im Internet zu finden.

Insofern habe ich kein schlechtes Gewissen, darauf zu verweisen und 
nicht als ehrenamtlichen Arschnachtrager nachzuschlagen und ihm 
vorzulesen.

Die Leute, die hier regelmäßig kompetent Auskunft geben, haben ihr 
Handwerk gelernt, indem sie sich drum gekümmert haben, und nicht indem 
sie für jeden Tastendruck sich von jemandem bedienen haben lassen.

Das geht jetzt nicht gegen die ursprüngliche Frage; ich will da 
niemanden groß anmeckern. Aber du hattest die Frage nach dem Sinn eines 
Forums erwähnt. Da bestehen durchaus unterschiedliche Ansichten...

M.M. nach ist die Frage durchaus berechtigt, wenn du das Problem damit 
hast. Berechtigt ist aber auch der Hinweis, daß man sowas in einem Buch 
findet.
Wenn du mit einem solchen Hinweis nicht weiterkommst, wirst du beim 
Programmieren nicht alt werden.

von Marco M. (marco_m)


Lesenswert?

"Nun kommt es vor, dass natürlich die neue Geschwindigkeit langsamer als
die alte ist, d.h. es wird verzögert. Die Beschleunigung ist daher
negativ."

Dann sollte da wohl eher:
1
ssBeschleunigung = ((ulGeschwindigkeitneu-ulGeschwindigkeitalt)*100)/ulGeschwindigkeitneu);
stehen, oder? Allerdings verstehe ich nicht, wie du so Beschleunigung 
berechnest. Wenn du Geschwindigkeit durch Geschwindigkeit teilst, dann 
bekommst du eine dimensionslose Zahl. Du brauchst aber m/s^2, musst 
daher (Die Differenz von) Geschwindigkeit durch Zeit teilen.

Nun wie auch immer:

Du musst nicht casten wenn du nicht willst. Sollte die Gefahr bestehen, 
dass das casten einen Überlauf produziert, weil ua,un >INT_MAX sein 
können, dann rechne einfach:
1
if (ua>un) 
2
 s=(int16_t)((100*(ua-un))/u2); /* So wie in deinem Code */ 
3
else 
4
 s=-(int16_t)((100*(un-ua))/u2); /* einfach umdrehen und später negativ machen */

Das dürfte besser sein, als mit int64_t anzufangen.

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
Noch kein Account? Hier anmelden.