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_ta=1054;
2
uint16_tb=84;
3
uint16_tc=1403;
4
5
doubleall=a+b+c;
6
doublea_=(double)a/all;
7
doubleb_=(double)b/all;
8
doublec_=(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_ta=1054;// Nach (double)a steht hier 2048 drin
2
uint16_tb=84;// Nach (double)b steht hier 855 drin
3
uint16_tc=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:> // Nach (double)a steht hier 2048 drin> // Nach (double)b steht hier 855 drin> // Nach (double)c steht hier 2048 drin
1. Was steht denn vorher drin?
2. Wie prüfst Du das?
Gruß
Jobst
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.
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.
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...
.... 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...
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.
Dr. Sommer schrieb:>> Compiler: ARM Yagarto> Ist der nicht völlig veraltet, mit dem letzten Update von 2012 und der> GCC Version 4.7.2?
Never touch a running system. :)