PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Rechnet der Arduino Falsch?



RoboterSindCool
29.12.2016, 14:39
Hallo,
ich will mit einem Joystick einen Roboter steuern. Dabei soll der Joystick sagen, welcher Motor (rechts, links) wie schnell fahren soll.
Auf jeden Fall muss ich dafür folgendes Rechnen:

geschwindigkeit_links = wert_y_map;
double geschw_rechts = 0;
geschw_rechts = (((-100 - (-83)) / (-100)) * 253);


Bei dieser Rechnung kommt doch tatsächlich 0 "für geschw_rechts" heraus!

Ich verstehe nicht! Double ist doch für kommazahlen gedacht! Wenn ich diese Rechnung in den Taschenrechner eingeben (genau so auch mit klammern) dann kommt 43.01 heraus! was rechnet der Arduino micro da?

Vielen Dank schon mal im vorraus!

Unregistriert
29.12.2016, 14:59
geschw_rechts = (((-100 - (-83)) / (-100)) * 253);

Ich verstehe nicht! Double ist doch für kommazahlen gedacht!

Rechts vom Gleichheitszeichen stehen aber nur Integer. Hänge mal an einer oder allen Zahlen ein .0 dran, also zB -100.0

Peter(TOO)
29.12.2016, 16:03
Hallo,

Der rechnet:

-100 - -83 = -17
-17 / -100 = 0.17 als Integer ergibt dies = 0 !!

MfG Peter(TOO)

Unregistriert
29.12.2016, 19:22
exakt, C rechnet immer nur mit der minimal notwendigen Genauigkeit, das ist bei reinen Int Zahlen eben reine Int Arithmetik.
Nur wenn verschiedene Datentypen in derselben Kalkulation auftauchen, wird automatisch auf die "höhere" gecastet.
100 ist Int, während 100.0 fp ist.

Also ist 17/100 per Int-Arithmetik 0 (Null) , während 17/100.0 automatisch auf fp gecastet wird, also als Ergebnis 0.17 ergibt.
Oder man muss explizit casten:
(float)17 / (float)100 = 0.17

Und davon ab, auf dem Arduino Micro ist double auch gar kein double sondern nur float.

RoboterSindCool
30.12.2016, 11:10
Hi und vielen vielen Dank für die schnellen Antworten!

Wenn ich es so rechne funktioniert es : geschw_rechts = (((-100.00 - (-83)) / (-100)) * 253);

also einfach hinter eine Zahl ".00" anfügen für float.

Vielen Dank

Geistesblitz
30.12.2016, 13:20
Mal ganz davon ab, dass deine Formel ziemlich umständlich geschrieben ist. Besser wäre wohl sowas:
geschw_rechts = (100-83)*253/100.00;

Ist genau dasselbe, nur ohne die ganzen Vorzeichen. Ich weiß jetzt nicht, ob der erste Teil noch mit Integer gerechnet wird und das Ergebnis dann beim Teilen durch 100.00 erst in Float umgewandelt, jedenfalls würde es so effizienter gerechnet werden. Aber zumindest finde ich es so übersichtlicher. Achja, sind das alles feste Zahlen oder werden Teile davon mal durch Variablen ersetzt werden? Dann wäre es sinnvoll, alle konstanten Werte zu einer Konstanten zusammenzufassen, die dann nur abgerufen werden muss.

Unregistriert
30.12.2016, 14:40
es ist nicht ungefährlich, bei Variablen zunächst alle Int Werte miteinander zu multiplizieren, bevor man dividiert.
In diesem Falle mag es gehene, wenn die Werte aber anders aussehen, gibt's Ärger:
Mal mit etwas anderen (größeren) Zahlen:

(1000-87)*253/100.0

ergibt zunächst
913
* 253
=> => Speicherüberlauf,
da Int nur von -32768 bis 32767 gehen (Int-Arithmetik !),
und dann führt auch eine anschließende Division /100.0 zu nichts sinnvollerem.

Wenn man also den Wertebereich der Rechnung nicht für alle möglichen Fälle sicher überschauen und von vornherein eingrenzen kann, ist ein rechtzeitiges Typecasting nach float der einzig sichere Ausweg,
d.h. Konstanten als floats schreiben mit Dezimalpunkt oder Int-Variablen per (float) vorher explizit casten, bevor man mit ihnen weiter herumrechnet.