Floating-Point-Problem
-
Hallo zusammen,
für die Ermittlung von Drehzahlen bekomme ich von einem externen Gerät Inkremente als int32_t geliefert. Daneben gibt es einen Skalierungswert. Dies ist z. B.
int32_t incVelo = 0; double scal = 0.001144;
Im ersten Schrit liefert der Sensor ausschließlich den Wert 0 zurück, was auch korrekt ist. Es wird im kommenden die folgende Rechenoperation ausgeführt:
double velo = static_cast<double>(incVelo) * scal;
Logischerweise soll hier 0 herauskommen, in einigen Fällen kommen aber Werte von ca. 20000 heraus.
Hat jemand solche Phänomene bereits beobachtet? Ich bin für jede Form von Hilfe dankbar.
s0n1c
PS: Ich verwendet C++14 mit g++ compiler.
-
Der Computer verrechnet sich nicht.
Da sind merkwürdige Programmiermuster selbst in dieser einen Zeile (Wozu der Cast?), die dafür sprechen, dass du nicht so ganz verstehst, was du da tust. Von daher wäre es nicht verwunderlich, wenn da irgendwelche handfesten Fehler an anderen Stellen vorliegen (leider nicht gezeigt), oder du einen Fehler bei deiner Fehleranalyse gemacht hast.
-
@s0n1c sagte in Floating-Point-Problem:
Hat jemand solche Phänomene bereits beobachtet?
Immer wenn so Dinge passieren, die nicht passieren dürften, liegt der Fehler anderswo. Nach den 3 hier gezeigten Zeilen wäre velo jedenfalls gleich 0. Kannst du versuchen, ein minimales, aber vollständiges (also kompilierbares) Beispiel zu erstellen, sodass man den Fehler reproduzieren kann?
-
@s0n1c sagte in Floating-Point-Problem:
in einigen Fällen kommen aber Werte von ca. 20000 heraus.
Wie ist der genaue Wert?
kann der aus einer Ganzzahl berechnet worden sein?Kann der Sensor auch negative Werte?
-
Vielen Dank für die bisherigen Beiträge!
Ein Beispiel habe ich mal zusammengestellt, der gesamte Code im Projekt ist hierfür zu groß.
#include <iostream> #include <stdlib.h> using namespace std; int main() { int32_t incVelo = 0; double scal = 0.001144; double velo = static_cast<double>(incVelo) * scal; cout << velo << endl; return 0; }
Die verwendeten Zahlen sind genau die, die auch auf unserem Gerät verwendet werden.
Um einige Fragen zu beantworten:
- Der Sensor kann auch negative Drehzahlinkremente ausgeben. Den Versuch habe ich nun auch mit drehenden Rädern gemacht und die erwarteten Geschwindigkeiten kamen bei der Berechnung auch heraus. Diese Ausreißer kommen immer noch vor, allerdings nur dann, wenn der zu erwartende Wert 0 ist. Wenn ich das Beispiel so kompiliere kommt in den meisten Fällen auch 0 heraus. Ich denke, dass der Fehler in der Berechnung mit einer 0 liegt und alle anderen Zahlen unkritisch sind.
- Die Berechnung kann nicht ausschließlich mit Ganzzahlen durchgeführt werden.
Nur eine Idee meinerseits: Da es mit allen Werten von incVelo außer 0 klappt könnte es sein, dass es irgendwelche Bits in der Variablen scal gibt, die in der Rechenoperation "kippen"? Das würde erklären, warum die Werte auf einmal in die Höhe schießen.
s0n1c
-
Schön, dass du ein Beispiel gemacht hast - aber da kommt doch korrekt 0 heraus: siehe auch https://ideone.com/BOo1Os Wir können dein Problem also nicht nachvollziehen, weil dein Beispiel den Fehler nicht zeigt.
Wie @SeppJ schon schrieb: der cast in
double velo = static_cast<double>(incVelo) * scal;
ist überflüssig. Du kannst einfachdouble velo = incVelo * scal;
schreiben, ohne dass sich etwas ändert. Aber das hat mit deinem Problem nichts zu tun.Nur eine Idee meinerseits: Da es mit allen Werten von incVelo außer 0 klappt könnte es sein, dass es irgendwelche Bits in der Variablen scal gibt, die in der Rechenoperation "kippen"? Das würde erklären, warum die Werte auf einmal in die Höhe schießen.
Nein, der Fehler ist anderswo.
-
@s0n1c sagte in Floating-Point-Problem:
Nur eine Idee meinerseits: Da es mit allen Werten von incVelo außer 0 klappt könnte es sein, dass es irgendwelche Bits in der Variablen scal gibt, die in der Rechenoperation "kippen"?
Nein.
Entweder ist die Berechnung von incVelo innerhalb der Lesefunktion fehlerhaft oder der Ort/Adresse wo incVelo bzw. velo steht wird irgendwie überschrieben (z.B. durch ein Arrayüberlauf).
-
@s0n1c sagte in Floating-Point-Problem:
Da es mit allen Werten von incVelo außer 0 klappt könnte es sein, dass es irgendwelche Bits in der Variablen scal gibt, die in der Rechenoperation "kippen"?
Tue mir mal bitte einen Gefallen. Füge den folgenden Code in deinen Code ein und schaue dir die genauen Sensordaten an. Ich möchte sicherstellen das der Sensor keine Ausreißer liefert.
printf("iv = %i | sf = %f | v = %f\n", incVelo, scal, velo);