Datentypkonvertierung uint16_t zu double

Gast #5069649
Moin,
bisher habe ich es immer vermieden mit float und double zu arbeiten, 
weil es mir unheimlich ist. Da ich nun aber auch sin + cos verwenden 
muss, komme ich nicht drumherum.

Nun habe ich auch schon das erste Problem. Ich habe drei Werte in 
uint16_t und ich benötige jeweils drei double Werte im Bereich von 0..1, 
die das Verhältnis wiederspiegeln. Also habe ich es wie folgt versucht 
zu lösen. (Vereinfachtes Beispiel)

Prozessor: ARM Cortex M3 (STM32F103)
Compiler: ARM Yagarto
1
uint16_t a = 1054;
2
uint16_t b = 84;
3
uint16_t c = 1403;
4

5
double all = a + b + c;
6
double a_ = (double)a / all;
7
double b_ = (double)b / all;
8
double c_ = (double)c / all;

Hier ist mir aufgefallen, dass der b Anteil viel zu groß erscheint. Also 
habe ich mir mal die konvertierten Zahlen ausgegeben:
1
uint16_t a = 1054;  // Nach (double)a steht hier 2048 drin
2
uint16_t b = 84;    // Nach (double)b steht hier 855 drin
3
uint16_t c = 1403;  // Nach (double)c steht hier 2048 drin

Kann das sein?! - So schlecht kann man doch gar nicht auf / abrunden bei 
der Typkonvertierung.

Was mache ich falsch?

Vielen Dank für eure Unterstützung.
Fabian schrieb:
> uint16_t a = 1054;  // Nach (double)a steht hier 2048 drin

Eventuell kommt auch nur der Debugger beim Anzeigen durcheinander. Der 
Compiler arbeitet ja intern mit den (32-bittigen) Registern, und für 
double müsste man gleich 2 zusamman auswerten.

Hier würde ich mir den generierten Assembler Code zusammen mit den 
Regsiter Inhalten genauer anschauen.

Vorsicht: Als ich das letzte Mal yagarto benutzt habe, war (*)printf für 
float Formate (%f etc.) kaputt. Zur Anzeige habe ich die Werte in 
Ganzzahlen zurück gewandelt. Die Anzeige der Variablen im Debugger 
sollte das aber nicht betreffen.
Gast
Fabian schrieb:
> uint16_t und ich benötige jeweils drei double Werte im Bereich von 0..1,
> die das Verhältnis wiederspiegeln.

Was für einen Compiler benutzt du?

Der Datentyp double ist bei vielen µC-Compilern nur Augenwischerei und 
wird tatsächlich als float umgesetzt, i.e. mit 7-8 signifikanten Stellen 
und nicht mit 15-16, wie man es vielleicht erwarten könnte.
Gast
Oh mann, da war ich völlig auf der falschen Spur. Das Problem lag ganz 
wo anders. Hinter a, b und c befinden sich in Wirklichkeit Pointer auf 
Werte und dieser Speicherbereich war nicht mehr gültig, da er im Stack 
lag. Nun funktioniert alles wie erwartet!

Vielen Dank euch, ich gehe jetzt mit gesenktem Kopf...
Gast
.... Aber Vorsicht bei deinem printf Format!

%u erwartet unsigned int, du hast uint_16
%f erwartet float, du hast double.

Möglicherweise funktioniert das implementierungsbedingt bei dir.
Du solltest die Variablen entsprechend den Vorgaben der Formatbezeichner 
casten.

Grüße, Adib.
Adib schrieb:
> Uhh, hab noch mal nachgeschaut. Printf kennt kein float.
> Also %f ist double.

So ist es, float immer schön nach double casten und char nach int.
Beim Keil C51 gibt es zwar einen Formatbezeichner für char-Zahlen, aber 
wenn man portabel sein will, besser nicht benutzen.
Die Ausgaben sind ja in der Regel für den langsamen Menschen, also muß 
man da nicht optimieren.
Adib schrieb:
> %f erwartet float, du hast double.

Wenn man keine Ahngung hat ... </Nuhrzitat>

Das %f würde auch mit double funktionieren - wenn man eine andere 
C-Library als Newlib verwendet. Die newlib braucht dafür leider relativ 
viel Speicherplatz auf dem Heap über malloc(), den man auf ARM Cortex-M 
eher selten hat. Aber es gäbe alternative sprintf() Implementationen.

Und %u nimmt auch uint16_t an...
Gast
Nennt sich glaube ich Optimierung. Nach der Umwandlung in 
Flieskommazahlen kräht kein Hahn mehr nach den Integervariablen. Daher 
wird deren Speicherplatz für andere schöne Werte benutzt. Der Debugger 
gibt Dir halt weiterhin den Wert aus der Speicherzelle aus, wo die 
Integervariable mal stand, als sie noch gebraucht wurde.
Es gibt zwar auch Versuche, dem Debugger Tips zu geben, ob eine Variable 
existiert. Die schießen aber unter Umständen über das Ziel hinaus, so 
dass Du einen Variableninhalt nicht angezeigt bekommst, obwohl die 
Variable noch existiert.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.