Die Fließkommazahlen hab ich anstatt der float-Variblen zum debuggen
eingesetzt.
Auf dem LCD kommt 2436116,21856 anstatt 2436116,31392
Was ist hier bloß los? Hängt das mit der Länge des strings zusammen?
Gruß
Frank
Frank wrote:
> Was ist hier bloß los? Hängt das mit der Länge des strings zusammen?
Eher mit der Länge eines floats bzw. double ( = 4 Bytes ).
Damit kannst du über den Daumen mit so um die 6 signifikanten
Ziffern rechnen. 2436115.50331110 verbraucht aber vor dem
Komma schon 7 signifikante Ziffern.
Hallo,
eigentlich irgendwie der Hammer, so ein mächtiger compiler, aber wenn
ich 2 fünfstellige Zahlen mit je 5 Nachkommastellen addieren will
(muss) ist Ende.
Das Beispiel aus dem 2. link bekomm ich leider nicht übersetzt:
1
> "make.exe" all
2
3
-------- begin --------
4
avr-gcc (GCC) 3.4.3
5
Copyright (C) 2004 Free Software Foundation, Inc.
6
This is free software; see the source for copying conditions. There is NO
7
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
main.c:13:21: dprintf.h: No such file or directory
15
main.c:25: warning: function declaration isn't a prototype
16
main.c:40: warning: function declaration isn't a prototype
17
main.c:47: warning: function declaration isn't a prototype
18
main.c: In function `f_check':
19
main.c:275: warning: implicit declaration of function `DebugPrintf'
20
main.c:65: warning: unused variable `a'
21
main.c:65: warning: unused variable `b'
22
main.c:68: warning: unused variable `sda'
23
main.c:68: warning: unused variable `sdb'
24
main.c:72: warning: unused variable `erg'
25
main.c:73: warning: unused variable `n'
26
main.c:74: warning: unused variable `x'
27
main.c:111: warning: unused variable `xm'
28
main.c:131: warning: unused variable `xi'
29
main.c: In function `main':
30
main.c:328: warning: implicit declaration of function `Initialization'
31
main.c:323: warning: unused variable `i'
32
main.c:323: warning: unused variable `m'
33
main.c:324: warning: unused variable `r32_a'
34
main.c:324: warning: unused variable `r32_b'
35
main.c:324: warning: unused variable `s32'
36
main.c:324: warning: unused variable `r1'
37
main.c:324: warning: unused variable `r2'
38
main.c:324: warning: unused variable `r3'
39
main.c:324: warning: unused variable `r4'
40
main.c:324: warning: unused variable `r5'
41
main.c:324: warning: unused variable `r6'
42
main.c:324: warning: unused variable `r7'
43
main.c:324: warning: unused variable `r8'
44
main.c:325: warning: unused variable `r64'
45
make.exe: *** [main.o] Error 1
46
47
> Process Exit Code: 2
oder gibt es noch eine andere Alternative.
Oder muss ich gar den mühsamen Weg von Bascom zu gcc wieder umnkehren
und mich dort nach floats umsehen.
Gruß
Frank
Hallo,
das falsche Ergebnis hatte ich doch ganz oben schon beschrieben.
Das grundsätzl. Problem ist wohl, wenn ich es richtig verstanden habe,
dass ein float schlicht nur 4 Byte abdeckt. Wenn, wie in meinem Fall,
die Ansprüche an Genauigkeit bzw. Stellenanzahl höher sind, ist eben
Feierabend - bzw. man hat oder kann sich zusätzl. 64bit Lib´s selber
basteln.....
Aber evtl. kann mir ja noch jemand bzgl. der obigen Fehlermeldungen auf
die Sprünge helfen.
Gruß
Frank
Hallo,
ich glaube, dass der Compiler mit 64Bit rechnet. Das sollte bei C
standard sein. Dann sollte bei der Addition das richtige rauskommen. Nur
wie kann ich das prüfen, wenn die Wandlungsfunktion nicht das richtige
Ergebnis liefert?
Wenn ich nämlich mit 32Bit rechne, kommt nur 2436116,5 raus. Also muss
irgendwo 64Bit Genauigkeit zugrunde liegen.
Warum versuchst Du nicht mal:
dtostrf(2436116.31392,16,5,hilf_string);
Hallo,
wie auch Karl heinz Buchegger oben schon schrieb, liegt es nicht an
dtostrf.
Es handelt sich hier auch nicht um c sondern um gcc, auch wenn ich die
genauen Unterschiede nicht aus der Hüfte aufzählen könnten.
In jedem Fall ganz schön frustierend.
Gruß
Frank
Gast wrote:
> ich glaube, dass der Compiler mit 64Bit rechnet. Das sollte bei C> standard sein.
C Standard sind mindestens 10 Dezimalstellen. De fakto erzwingt das ein
64-bit Floating-Point Format.
Soweit der Standard. AVR-GCC hingegen implementiert nur das 32-Bit
Floating-Point Format. Wobei möglich ist, dass jene Rechnungen mit
Konstanten, die GCC selbst durchführt, mit voller Genauigkeit
stattfinden.
Hallo,
das Ergebnis 2436116,21856 ist im 32Bit Format nicht darstellbar:
2436116,21856 / 2^22 = 0,5808153673553466796875
Die Mantisse einer 32Bit FP-Zahl hat 23 Stellen:
0,5808153673553466796875 * 2^24 = 9744464,87424
sie muss also gerundet 9744465 betragen.
9744465 * 2^-24 * 2^22 = 2436116,25
Die Genauigkeit beträgt also maximal 0,25. Das Ergebnis scheint aber
genauer.
Wie rechnet also dtostrf wenn 32Bit FP zugrunde liegt?
Deswegen:
dtostrf(2436116.31392,16,5,hilf_string);
Was kommt denn da raus? Darf ich überhaupt 5 Nachkommastellen verlangen?
@Frank
>>Das Beispiel aus dem 2. link bekomm ich leider nicht übersetzt:
Das main.c ist nen Testprogramm für den Code aus avr_f64.c und
avr_f64.h, das brauchst Du nicht. Übersetze einfach avr_f64.c und binde
das headerfile in Deine Applikation ein, fertig ist die Laube. Wenn Du
das main.c zum Test verwenden willst muß Du es z.B. bzgl. der includes
und Ausgaben anpassen.
@Jörg
>>Wenn sich nur irgendeiner dieser hellen Köpfe mal aufraffen könnte,
:-) THX. Ich hatte mir vorher die 32 Bit float Implementation angekuckt
um zu sehen, ob man die 64 Bit Implementation nicht daran anlehnen
könne. Im Wesentlichen haben mich 3 Dinge abgeschreckt:
- Die 32Bit float lib ist in Assembler geschrieben, das war mir im
Tausch gegen Geschwindigkeitsvorteile zu aufwendig.
- Die 32Bit float lib scheint mir ziemlich vollständig bezüglich der
anzuwendenden Norm, also Behandlung von +/-0, 1/0, NaNs, Inf,
trigonometrischen Funktionen. etc. . Sowas ist sehr viel aufwendiger als
nen Code, der 'normale' Zahlen richtig rechnet.
- Die Code-Konventionen und das 'framework' für eine einbindbare 64-Bit
Implementation sind mir völlig unbekannt.
Sporadisch gibt es ja für 64-Bit floats Interessenten, die auch an der
Stelle tatkräftig weiterschrauben, wie z.B. Florian K. . Ich habe
Interesse und Lust mich an einer 64Bit AVR Implementation zu beteiligen.
Ich habe allerdings keine Ahnung, wie sowas einzustielen ist: Wie bringt
man den Code an die 'Hüter' heran? 'Darf' man sowas in C machen? Was ist
der formale Rahmen, also z.B. die #ifdef-Orgien in den headerfiles?
Meine Kenntnisse und Kräfte sind schwach, aber die würde ich einsetzen.
Wllst/kannst Du sowas lostreten?
Cheers
Detlef
Hallo Detlef,
zunächst mal vielen Dank. Aber so einfach scheint das nicht zu sein,
oder ich bin zu blöd.
Ich hab die avr_f64.c ins makefile eingetragen und #include <avr_f64.h>
im main.c sowie die beiden Datein ins Projektverzeichnis kopiert.
Beim Übersetzen motzt er zunächst über
>main.c:12:21: dprintf.h: No such file or directory
wenn ich in der avr_f64.h die dprintf.h auskommentiere wirds kriminell:
1
> "make.exe" all
2
3
-------- begin --------
4
avr-gcc (GCC) 3.4.3
5
Copyright (C) 2004 Free Software Foundation, Inc.
6
This is free software; see the source for copying conditions. There is NO
7
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Du könntest Dir die Fehlermeldungen auch mal selber durchlesen:
main.c:11:20: common.h: No such file or directory
main.c:12:18: main.h: No such file or directory
main.c:13:21: dprintf.h: No such file or directory
Frank wrote:
> Klar hab ich die selber gelesen, ich hab die *.h-Dateien nur nicht> gefunden, daher habe ich nochmals gefragt.
Schon. Aber was sollen wir dann damit anfangen? Wenn du die Dateien
auf deinem Rechner nicht findest, werden wir sie hier aus der Ferne
auch nicht finden :-)
Hallo,
bin etwas irritiert, Karl-Heinz, Du hast mir mit einem Deiner links
einen download empfohlen, bei dem wohl über die Standard-Installation
von gcc/WIN-AVR hinaus Dateien erforderlich sind. Diese suche ich nun.
Da auch ich keine Fernsuche auf dem Rechner des Verfassers leisten kann,
hatte ich angenommen, die community hier hätte dieses Thema bereits mit
gängigen tools in den Griff bekommen und könnte einem relativen Anfänger
kurz auf die Beine helfen.
Gruß
Frank
Frank, bitte nehme mal meinen post von oben zur Kenntnis, da steht:
>>Wenn Du das main.c zum Test verwenden willst muß Du es z.B. bzgl. der >>includes
und Ausgaben anpassen.
Das ist geschneidert als Muster, wie man Tests auf dem eigenen AVR board
starten kann. Konkret: die includes von main.h, dprintf.h und common.h
rauskommentieren. 'Initialization' auch rausschmeissen, `DebugPrintf'
durch Dein printf ersetzen.
Probiers mal.
Cheers
Detlef
Frank wrote:
> eigentlich irgendwie der Hammer, so ein mächtiger compiler, aber wenn> ich 2 fünfstellige Zahlen mit je 5 Nachkommastellen addieren will> (muss) ist Ende.
Wenn du die Zahlen 1234141341234123412411341234124314.51351 und
1234123412341341234123432413412341324.13531 addieren willst, wirst
du, obwohl sie nur ,,je 5 Nachkommastellen'' haben, bei nahezu
jedem Compiler an die Grenzen stoßen. Es ist halt nicht nur der
Inhalt der Nachkommastellen, sondern auch derer vor dem Komma von
Bedeutung.
GCC selbst kann durchaus bis 80 oder 128 bit Gleitkommaarithmetik.
Jedoch ist die konkrete Gleitkommaimplementierung immer eine Sache
der Zielmaschine. Für den AVR hatten seinerzeit halt diejenigen,
die den GCC portiert haben, mal befunden, dass 32-bit-Arithmetik
bereits so viele Ressourcen schluckt, dass man nicht versucht hatte,
noch mehr als das zu machen. Es war durchaus auch gängig für andere
8-bit-Architekturen, das relativ berühmte Turbo-C auf CP/M (auf dem
Z80) konnte auch nicht mehr. Die AVRs dieser Zeit reichten so
ungefähr vom AT90S1200 bis zum AT90S8535 (mit einem ATmega103, der
noch in den Kinderschuhen steckte), dafür war diese Entscheidung wohl
gar nicht so unangemessen. Selbst C hat es bis kurz vor der
Verabschiedung des C99-Standards noch nicht erzwungen, dass ein double
mit mehr als 32 bits implementiert wird. Diese Änderung war erst kurz
vor der Verabschiedung des tatsächlichen Standards reingekommen. 64
bits werden auch heute nicht vorgeschrieben, aber effektiv sind die
Anforderungen so, dass man sie mit einer 32-bit-Implementierung nicht
erfüllen kann. 48 Bits müssten reichen für die Forderungen des
Standards, aber das wiederum kennt GCC nicht als Datenformat.
> Es war durchaus auch gängig für andere 8-bit-Architekturen,> das relativ berühmte Turbo-C auf CP/M (auf dem> Z80) konnte auch nicht mehr.
Ich will ja nicht mäkeln, aber bist Du Dir da sicher? Die Turbo-Cs, die
ich kenne, sind für 8086 und -als ziemlicher Exot- für 68k entwickelt
worden.
Turbo-Pascal hingegen gab es für CP/M, auch auf Z80.
Hallo Jörg,
ähm,
>> eigentlich irgendwie der Hammer, so ein mächtiger compiler, aber wenn>> ich 2 fünfstellige Zahlen mit je 5 Nachkommastellen addieren will>> (muss) ist Ende.>Wenn du die Zahlen 1234141341234123412411341234124314.51351 und>1234123412341341234123432413412341324.13531 addieren willst, wirst>du, obwohl sie nur ,,je 5 Nachkommastellen'' haben, bei nahezu>jedem Compiler an die Grenzen stoßen. Es ist halt nicht nur der>Inhalt der Nachkommastellen, sondern auch derer vor dem Komma von>Bedeutung.
ich hatte nur von 5-stelligen mit je 5 Nachkommastellen gesprochen. Dein
Beispiel ist 35-stellig mit 5 Nachkommastellen. Wie mir das jetzt
weiterhilft weiss ich nicht.
Gruß
Frank
Die Anzahl von Nachkommastellen bei floating-point-Darstellung muss man
normiert sehen, und zwar immer auf ein Format mit einer
Vorkommastelle.
Das ist eben das Grundprinzip des floating point - des "Gleitkommas"
oder der "Fließpunktes".
Bei der Ein- und Ausgabe lassen sich solche Werte zwar beliebig anders
darstellen, die interne Repräsentation arbeitet aber immer in diesem
normierten Format (und dazu noch binär, aber das ist 'ne andere und fürs
Grundprinzip nicht so wichtige Geschichte).
Die Exponentialschreibweise bringt hier Aufklärung:
12345.67891 ist 1.234567891E5 (* 10^5)
Aus "Fünfstellig mit fünf Nachkommastellen" werden so jedenfalls neun
Nachkommastellen. Und die kann float (32 bit) nicht auflösen.
Ebenso wie aus "12stellig ohne Nachkommastellen" tatsächlich elf
Nachkommastellen werden:
12345679012 = 1.23456789012E12 (* 10^12)
Na, wird's klarer?
>Warum muß es überhaupt so genau sein?
Die Frage hatte ich mir auch gestellt und auf irgendwelche Antworten auf
die Eingangsfrage verzichtet, bis wenigstens das geklaert ist. Werde ich
auch weiter so halten.
Matth
> Die Anzahl von Nachkommastellen bei floating-point-Darstellung muss man> normiert sehen, und zwar immer auf ein Format mit einer> Vorkommastelle.
Genua genommen sind es 0 Vorkommastellen, da der Wert vor dem Komma
immer gleich ist.
Dieser Streit um Vor- und Nachkommastellen bringt mehr Verwirrung als
nötig. Die Anzahl Stellen insgesamt ist entscheidend, egal ob sie vor
oder hinter dem Komma stehen.
Und der Wert vor dem Komma ist nur dann immer gleich, wenn man das ganze
binär betrachtet. Nicht jedoch wenn man sich der Übersichtlichkeit
halber im dezimalen System bewegt.
Die Anzahl Dezimalstellen, mit denen das Zielsystem mindestens rechnet,
lässt sich in <float.h> in FLT_DIG/DBL_DIG/LDBL_DIG ablesen.
Rufus t. Firefly wrote:
> Turbo-Pascal hingegen gab es für CP/M, auch auf Z80.
Klar, darauf hatte ich mich bezogen. Das war meiner Erinnerung nach
auch noch kein IEEE-754-Format, sondern irgendwas anderes.
Frank wrote:
>> Ich hab die avr_f64.c ins makefile eingetragen und #include <avr_f64.h>> im main.c sowie die beiden Datein ins Projektverzeichnis kopiert.>
Ist das Dein Fehler? Sollte dort nicht #include "avr_f64.h" stehen?
Includes in spitzen Klammern werden auf meinem Rechner in:
C:\WinAVR-20071221\avr\include
gesucht.
> Die Anzahl Stellen insgesamt ist entscheidend, egal ob sie vor> oder hinter dem Komma stehen.
Allerdings.
> Und der Wert vor dem Komma ist nur dann immer gleich, wenn man das> ganze binär betrachtet.
So werden Gleitkommazahlan ja in der Regel auch gespeichert.
Hallo Frank,
ich behaupte jetzt einfach mal, dass der Anwender Deines Systems eine
derartige Genauigkeit überhaupt nicht benötigt (und auch nicht sehen
will).
Kannst Du kurz beschreiben, welche Größe durch diesen Wert dargestellt
werden soll? Evtl. ist ja eine wesentlich niedrigere Stellenzahl
vollkommen ausreichend. Jedenfalls möchte ich keine physikalische Größe
mit dieser Genauigkeit um die Ohren gehauen bekommen, da
Normalsterbliche solche Messgenauigkeiten niemals erreichen können ;-)
Zur Not kannst Du auch ganzzahlig rechnen (immerhin ca. zehnstellig) und
dann den Dezimalpunkt entsprechend reinsetzen.
ciao
Marcus