Forum: Mikrocontroller und Digitale Elektronik Der Microcontroller und seine Datentypen


von Helge (Gast)


Lesenswert?

Hallo zusammen!

Ich habe mal eine Frage bezüglich der Datentypen auf einem 
Microcontroller.

Ich habe 16Bit im Controller. Also würde ich ja vorzugsweise mit int16 
oder besser noch mit uint16 arbeiten, richtig?

Dies ist aber leider nicht immer möglich, manchmal reichen die 
Datentypen nicht, also muss ein Double oder Float her.

Wie sehr wirken sich diese Datentypen auf die Rechengeschwindigkeit aus? 
Gibt es da irgendwo eine Info zu, vielleicht ein Link oder so?

Und was ist mit int32 und int64 Variablen? Sind die noch geeigneter als 
double? Sind ja auch 64Bit.

Vielen Dank für jede Info.

von Karl H. (kbuchegg)


Lesenswert?

Helge schrieb:

> Ich habe 16Bit im Controller. Also würde ich ja vorzugsweise mit int16
> oder besser noch mit uint16 arbeiten, richtig?

Im Normalfall kann man davon ausgehen, dass eine CPU mit ihrer Leib und 
Magen-Bitbreite am besten und damit auch am schnellsten umgehen kann.

Bei einer  8 Bit CPU   sind das daher  8 Bit Datentypen
          16                          16
          32                          32

Allerdings ist die Sache nicht so einfach zu sehen. So haben zb auch 8 
Bit CPUs des öfteren Befehle zur Bearbeitung von 16 Bit Datentypen 
eingebaut.

> Dies ist aber leider nicht immer möglich, manchmal reichen die
> Datentypen nicht, also muss ein Double oder Float her.

Ich nehm das mal als gegeben hin.
Oftmals kann man nämlich auch ganz gut ohne Double oder Float leben.

> Wie sehr wirken sich diese Datentypen auf die Rechengeschwindigkeit aus?
> Gibt es da irgendwo eine Info zu, vielleicht ein Link oder so?

Datenblatt bzw. INstuction Set des jeweiligen Prozessors.
Wenn dort keine Unterstützung für bestimmte Datentypen erkennbar ist, 
dann müssen diese in Software emuliert werden. Wenn aber eine bestimmte 
Operation durch Software nachgebildet werden muss, ist das klarerweise 
immer langsamer, als eine Operation, die die CPU bereits in Hardware 
kann.

> Und was ist mit int32 und int64 Variablen? Sind die noch geeigneter als
> double? Sind ja auch 64Bit.

Musst du im Datenblatt bzw. in der konkreten IMplementierung nachsehen.
Im Zweifelsfall macht man sich ein paar Testprogramme, dann weiß man es 
ganz genau.

von Helge (Gast)


Lesenswert?

Da muss ich nochmal schauen, dazu habe ich im Datenblatt noch nie was 
gesehen.

Aber nur mal als Beispiel:

Letztens hatte ich so ein Problem. Ich wollte einen Behälter berechnen. 
Dazu konnte man Angaben über diesem machen. Also Durchmesser, Höhe, und 
unter anderem die Wandstärke, um den wirklichen Durchmesser zu 
bestimmen.

So, die Tankgröße könnte man noch gut in der Form mm.cc (also meter und 
centimeter) angeben, das ist wohl ausreichend, aber die Wandstärke muss 
ja schon in mm angegeben werden können.

Jetzt kann ich mm.cc ohne Probleme in cm umrechnen, aber halt nicht mit 
mm verrechnen. Also alles in mm umrechnen. Oder Kommazahlen benutzen.

Wenn man jetzt aber bedenkt, dass man schon bei einem Zylinder PI*r^2*h 
rechnen muss, so werden die Zahlen recht schnell recht gross.

Da wir ja ohne Komma arbeiten wollen, shiften wir PI um 100000 nach 
links und verrechnen diese ganze Zahl. Danach wieder dadurch teilen. 
Aber erstmal ein Multiplikator von 300000.

Also wäre ein Tank von 20m Höhe und 10m Breite:

10000*10000*31415x*20000

Und es könnte ja noch mehr sein...

Kann mir jemand mal sagen, wie ich das am Besten lösen kann? Vielleicht 
ist es ja trivial und ich sehe die gute Lösung ohne 64Bit Variablen 
nicht.

Danke

von Karl H. (kbuchegg)


Lesenswert?

Helge schrieb:

> Also wäre ein Tank von 20m Höhe und 10m Breite:
>
> 10000*10000*31415x*20000
>
> Und es könnte ja noch mehr sein...

In dem Moment, in dem deine Zahlen einige Größenordnungen auseinander 
liegen, wie bei dir Meter und Millimeter, führt meistens kein Weg mehr 
an Floating Point vorbei.
Aber den Fall hat man nicht sooooo oft im µC-Bereich

von otto (Gast)


Lesenswert?

..ist eben die Frage, ob man bei 10m Tankdurchmesser die 5mm Wandstärke 
vernachlässigen kann. Meistens kann man es und es ist möglich, mit 
Centimeter oder gar Dezimeter als Basiseinheit zu rechnen. Dann werden 
die Zahlen auch nicht so groß.

von Helge (Gast)


Lesenswert?

otto schrieb:
> ..ist eben die Frage, ob man bei 10m Tankdurchmesser die 5mm Wandstärke
> vernachlässigen kann

Gut, ist natürlich auch ein Argument, klar.

Aber geht ja mehr um generell. Bin ich denn mit einem uin64_t noch 
besser beraten als mit einem Double?

Ich benutze einen MSP, der hat sicher keine Unterstützung für 
Fließkommazahlen in Hardware.

von Floh (Gast)


Lesenswert?

Helge schrieb:
> Aber geht ja mehr um generell. Bin ich denn mit einem uin64_t noch
> besser beraten als mit einem Double?

Ja, da der Compiler alle Byte des Datetyps uint64_t gleichbehandeln 
kann, was bei float nicht der Fall ist.
:-)

von Peter D. (peda)


Lesenswert?

Helge schrieb:
> Aber geht ja mehr um generell.

Generell gibbet nich, es kommt immer auf den konkreten Compiler an.

> Bin ich denn mit einem uin64_t noch
> besser beraten als mit einem Double?

Z.B. sind beim AVR-GCC int64_t grottenschlecht implementiert, da ist 
sogar float kleiner und schneller.
Und double kann der AVR-GCC garnicht.


Peter

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Wenn sich ein Problem mit Geitkommaarithmetik wesentlich leichter lösen 
lässt, als mit Ganzzahlarithmetik, dann sollte man das auch so machen, 
wenn dadurch keine wesentlichen Nachteile entstehen.

Ein wesentlicher Nachteil wäre es, wenn das Programm dadurch nicht mehr 
im Speicher Platz hat, oder die Ausführung zu lange dauert.

Grüße,

Peter

von Karl H. (kbuchegg)


Lesenswert?

Peter Diener schrieb:
> Wenn sich ein Problem mit Geitkommaarithmetik wesentlich leichter lösen
> lässt, als mit Ganzzahlarithmetik, dann sollte man das auch so machen,
> wenn dadurch keine wesentlichen Nachteile entstehen.
>
> Ein wesentlicher Nachteil wäre es, wenn das Programm dadurch nicht mehr
> im Speicher Platz hat, oder die Ausführung zu lange dauert.

Ein wesentlicher Nachteil wäre es auch, wenn sich dadurch die 
Programmlogik verändert :-)

  double a = 0.0;

  for( i = 0; i < 10; ++i )
    a += 0.1;

wer sich danach erwartet, dass a exakt den Wert 1.0 hat, hat mit 
Zitronen gehandelt.

Solche Probleme können einem den ganzen Tag versauen.

von Helge (Gast)


Lesenswert?

Peter Diener schrieb:
> Wenn sich ein Problem mit Geitkommaarithmetik wesentlich leichter lösen
> lässt, als mit Ganzzahlarithmetik, dann sollte man das auch so machen

Naja genau davor stehe ich grad. Nur unterm Strich brauchen die uint64 8 
Byte und die Doubles auch. Da werde ich wohl die uints vorziehen, oder? 
Ich arbeite mit dem IAR Compiler.

Die Fließkommatypen sind schon vom reinen Programmieren her einfacher, 
finde ich, da man nicht mit Multiplikatoren und Divisoren rumhantieren 
muss an den richtigen stellen. Gut, bei meinem Tank ist die 
Nachkommastelle wegen einem Liter Unterschied nicht so wichtig, aber 
generell leidet ja auch noch die Genauigkeit ohne Fließkomma.

Nur lese ich halt hier im Forum so oft, dass man Doubles tunlichst 
vermeiden sollte.

Ich mein, es ist ja wenn nicht ein Double, sondern dann sind mehrere der 
beteiligten Zahlen ein double - das verlangsamt / verschlechtert das 
doch immer weiter, oder?

von Helge (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> wer sich danach erwartet, dass a exakt den Wert 1.0 hat, hat mit
> Zitronen gehandelt.

Klar, darüber bin ich mir im Klaren. Auf ne glatte Null kommt man auch 
nie mehr zurück dabei.

von Karl H. (kbuchegg)


Lesenswert?

Helge schrieb:

> Naja genau davor stehe ich grad. Nur unterm Strich brauchen die uint64 8
> Byte und die Doubles auch.

Das ist gar nicht mal so entscheidend. double sind viel aufwändiger zu 
rechnen.

> Da werde ich wohl die uints vorziehen, oder?
> Ich arbeite mit dem IAR Compiler.
>
> Die Fließkommatypen sind schon vom reinen Programmieren her einfacher,
> finde ich, da man nicht mit Multiplikatoren und Divisoren rumhantieren
> muss an den richtigen stellen.

Das ist genau die naive Sichtweise der Dinge, bei der dann hinten nach 
etwas rauskommt, was mit dem korrekten Ergebnis nur noch sehr wenig zu 
tun hat.

> Gut, bei meinem Tank ist die
> Nachkommastelle wegen einem Liter Unterschied nicht so wichtig, aber
> generell leidet ja auch noch die Genauigkeit ohne Fließkomma.

Und erst mit!

Mit float hast du so um die 5 bis 6 signifikante Ziffern. Signifikante, 
nicht 'nach dem Komma' !

bei einer Zahl 1234.56
hast du bereits 4 signifikante Ziffern vor dem Komma aufgebraucht. Bei 
einer Zahl 25 Millionen, also 25000000.0 ist bereits die Hunderterstelle 
mehr als fraglich, vor allen Dingen wenn man dann auch noch ein wenig 
rumgerechnet hat (wie es bei dir der Fall ist)

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Wenn das Problem nicht zeitkritisch ist, würde ich das einfach in Float 
oder je nach benötigter Präzision auch in Double rechnen. Das Verwenden 
von 64 Bit Integern macht aus meiner Sicht keinen Sinn, es beschleunigt 
die ganze Sache nur unwesentlich, macht dafür das Programm aber 
unübersichtlich und schlecht nachzuvollziehen.

Grüße,

Peter

von Helge (Gast)


Lesenswert?

Keine Frage, klar. Ein float würde hier sowieso nicht in Frage kommen. 
Wenn dann ein double, aber auch der hat seine Grenzen, sicher.

Ich versteh schon was du meinst. Momentan läuft es mit uint64_t, ein 
32er reicht leider an manchen Stellen nicht, zumindest bei der 
Millimeter-Variante. Aber evtl. ist ja echt die Wandstärke unnötig.

Bei nem kleinen Tank ist die Wand nicht sehr dick wahrscheinlich und bei 
nem großen wird sie im Verhältnis zum Inhalt irrelevant.

Würde ich jtzt mal so behaupten. Wahrscheinlich ist der Messfehler 
größer.

von Karl H. (kbuchegg)


Lesenswert?

Helge schrieb:

> Würde ich jtzt mal so behaupten. Wahrscheinlich ist der Messfehler
> größer.


Davon kannst du ausgehen.
Und wie rund dein Tank bei den Dimensionen tatsächlich ist, möchte ich 
auch nicht genauer hinterfragen.

von Helge (Gast)


Lesenswert?

Peter Diener schrieb:
> macht dafür das Programm aber
> unübersichtlich und schlecht nachzuvollziehen

In wie fern? Also nur falls ich in die richtige Richtung tippe: Ich 
programmiere in C, nicht in Assembler, das hab ich leider nicht drauf.

Auf jeden Fall ist es nicht unübersichtlicher als ein 32 oder 16 Bit 
Typ.

von Peter D. (peda)


Lesenswert?

Helge schrieb:
> Nur lese ich halt hier im Forum so oft, dass man Doubles tunlichst
> vermeiden sollte.

Nunja die Zeiten ändern sich, die Speicher werden größer und die CPUs 
schneller, da kann man auch mal Dogmen umstoßen.

Wenns nur für ne Anzeige für den langsam lesenden Menschen geht, da 
langweilt sich ne 8Bit-CPU auch bei double zu Tode.

In der Regel schadet es aber nichts, wenn man statt Double Float nimmt.
Double braucht man eigentlich nur bei extremer Genauigkeit, z.B. in der 
Astronomie.

Praktische Meß-und Regelanwendungen kommen immer mit float aus, oftmals 
sind ja die Analog-IOs auch nur 8..16 Bit breit. Wozu also mit unnützer 
Genauigkeit rechnen, um sie hinterher wieder wegzuschmeißen.


Peter

von Helge (Gast)


Lesenswert?

OK, du hast mich überzeugt!

Besten Dank!!!

von Peter D. (pdiener) Benutzerseite


Lesenswert?

>> macht dafür das Programm aber
>> unübersichtlich und schlecht nachzuvollziehen

>In wie fern? Also nur falls ich in die richtige Richtung tippe: Ich
>programmiere in C, nicht in Assembler, das hab ich leider nicht drauf.

Es ist einfacher nachzuvollziehen, wenn das Problem direkt so da steht, 
wie man es auf dem Papier rechnen würde. Das Verwenden von 
Ganzzahldatenypen erfordert, dass man alles auf Ganzzahlen normiert, die 
Variablen also Vielfache der eigentlich zu berechnenden Zahl beinhalten. 
Damit das richtig schnell geht, verwendet man nicht Zehnerpotenzen als 
Multiplikatoren, sondern Zweierpotenzen. Damit lassen sich Divisionen 
und Multiplikationen als Bitschiebeoperationen ausdrücken. Wenn man das 
so macht, kann es sein, dass in einer Variable das 65536 fache des 
eigentlich zu berechnenden Werts steht, in einer anderen das 256 fache. 
Da noch richtig durchzublicken ist, wenn das Problem etwas komplexer 
ist, nicht mehr einfach.

Abhilfe schaffen Fixpunktbibliotheken, wie z.B. IQmath von Ti, was man 
beispielsweise auf Festpunkt-DSPs verwendet. Soweit ich weiß, gibt es 
aber für den MSP430 keine Fixpunktbibliothek, man muss das alles selbst 
von Hand durchdenken.

Grüße,

Peter

von Helge (Gast)


Lesenswert?

Peter Diener schrieb:
> Wenn man das
> so macht, kann es sein, dass in einer Variable das 65536 fache des
> eigentlich zu berechnenden Werts steht, in einer anderen das 256 fache.

OK, so trickreich habe ich da noch nie drüber nachgedacht.

Wenn nehme ich ganze Zehnerpotenzen. Aber gut, ist natürlich auch ein 
guter Weg.

von Karl H. (kbuchegg)


Lesenswert?

Peter Diener schrieb:

> Multiplikatoren, sondern Zweierpotenzen. Damit lassen sich Divisionen
> und Multiplikationen als Bitschiebeoperationen ausdrücken. Wenn man das
> so macht, kann es sein, dass in einer Variable das 65536 fache des
> eigentlich zu berechnenden Werts steht, in einer anderen das 256 fache.

@Helge
Im Grunde ist man dann schon auf dem Weg, der einen letztendlich zu 
Floating Point führt, nur dass diese Faktoren in der Zahl selber mit 
drinnen sind und von den Rechenroutinen mit berücksichtigt werden.

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.