Forum: Compiler & IDEs gcc oder ich kann nich rechnen.


von Frank (Gast)


Lesenswert?

Hallo,

hab mal wieder ein kleines Problem:

1
 char hilf_string[16];
2
3
 ..................
4
5
 dtostrf(2436115.50331110+0.8106100000000,16,5,hilf_string);
6
  
7
 LCD_Print(0,0,hilf_string);
8
9
 ..............

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Frank (Gast)


Lesenswert?

float ist - wenn ich das richtig verstehe - also für meinen Zweck nicht 
geeignet.  Welcher Datentyp hilft mir hier?

Vielen Dank im Voraus

Frank

von Karl H. (kbuchegg)


Lesenswert?

Frank wrote:
> float ist - wenn ich das richtig verstehe - also für meinen Zweck nicht
> geeignet.  Welcher Datentyp hilft mir hier?
>

Beitrag "Gleitkomma-Bibliothek für AVR"
Beitrag "64 Bit float Emulator in C, IEEE754 compatibel"

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl heinz Buchegger wrote:

> Beitrag "Gleitkomma-Bibliothek für AVR"
> Beitrag "64 Bit float Emulator in C, IEEE754 compatibel"

Wenn sich nur irgendeiner dieser hellen Köpfe mal aufraffen könnte,
stattdessen an einer GCC-Integration einer derartigen Bibliothek
zu arbeiten...  So bleibt es leider immer irgendwie eine Krücke.

von Frank (Gast)


Lesenswert?

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.
8
9
10
Compiling: main.c
11
avr-gcc -c -mmcu=atmega8 -I. -gdwarf-2 -DF_CPU=16000000UL  -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.lst  -std=gnu99 -MD -MP -MF .dep/main.o.d main.c -o main.o 
12
main.c:11:20: common.h: No such file or directory
13
main.c:12:18: main.h: No such file or directory
14
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

von Gast (Gast)


Lesenswert?

Hallo,
liegt nun der eigentliche Fehler am Compiler oder an der 
Wandlungsfunktion dtostrf?

Was kommt denn bei der Addition heraus?

von Frank (Gast)


Lesenswert?

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

von Gast (Gast)


Lesenswert?

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);

von Frank (Gast)


Lesenswert?

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

von Andreas K. (a-k)


Lesenswert?

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.

von Gast (Gast)


Lesenswert?

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?

von Detlef _. (detlef_a)


Lesenswert?

@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

von Frank (Gast)


Lesenswert?

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.
8
9
10
Compiling: main.c
11
avr-gcc -c -mmcu=atmega8 -I. -gdwarf-2 -DF_CPU=16000000UL  -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.lst  -std=gnu99 -MD -MP -MF .dep/main.o.d main.c -o main.o 
12
main.c:11:20: common.h: No such file or directory
13
main.c:12:18: main.h: No such file or directory
14
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

Was ist zu tun?

Vielen Dank im Voraus.

Gruß

Frank

von Frank (Gast)


Lesenswert?

hat hier keiner eine Idee ?

Gruß

Frank

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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

von Frank (Gast)


Lesenswert?

Klar hab ich die selber gelesen, ich hab die *.h-Dateien nur nicht 
gefunden, daher habe ich nochmals gefragt.

Gruß

Frank

von Karl H. (kbuchegg)


Lesenswert?

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 :-)

von Frank (Gast)


Lesenswert?

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

von Detlef _. (detlef_a)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> 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.

von Frank (Gast)


Lesenswert?

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

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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?

von Oliver (Gast)


Lesenswert?

Was dann zur der Frage führt:

Warum muß es überhaupt so genau sein?

Oliver

von dachs (Gast)


Lesenswert?

>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

von Rolf Magnus (Gast)


Lesenswert?

> 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.

von Andreas K. (a-k)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Frank J. (frajo)


Lesenswert?

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.

von Rolf Magnus (Gast)


Lesenswert?

> 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.

von Marcus Woletz (Gast)


Lesenswert?

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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.