Hallo,
also es geht darum aus vielen Werten einen Mittelwert zu berechnen.
Nun diese Werte können sich zwischen 0 und 20000 bewegen.
Sollte ich nun 4 mal 20000 hereinbekommen habe ich einen overflow,
da ein integer ja nur bis 65535 geht.
Nun wie initialisier ich einen long richtig auf dem ATMEGA8?
Vor einiger Zeit hatte ich ein ähnliches Problem, hab mich dann aber
nicht weiter mit long beschäftig da ich einen anderen Lösungsansatz
gefunden habe.
Julian Schild schrieb:
>> Aber warum kann ich nicht einfach
1
longlPuffer;
schreiben?
Kannst du
uint32_t macht nur etwas klarer, dass du hier 32 Bit haben willst. Bei
einem long alleine, weiß wieder kein Mensch auswendig, wieviele Bits das
sind. Auf deinem AVR sind es 32, auf einem PC sind es wieviele?
Pass lieber auf, dass du hier
Hallo Karl,
kannst du dich ein wenig genauer ausdrücken?
Da ich es selber geschrieben habe bin ich der Überzeugung, dass es
passt.
Also die Selbstkorrektur ist immer um einiges schwieriger ;).
Ich denk es mir so:
Ich addiere 3 Elemnte von diesem Feld um dividiere durch 3.
Somit sollte es eigentlich der Mittelwert sein.
MFG
Die Division durch 4 lässt sich einfach durch das verschieben um 2
Stellen
darstellen. Bevor die Werte nun ins Array gehen werden sie bereits
ge4telt um niemals so hohe Werte zu erreichen, dass man einem Overflow
nahe kommt.
MFG
Hi Julian,
Julian Schild schrieb:
> Bevor die Werte nun ins Array gehen werden sie bereits> ge4telt um niemals so hohe Werte zu erreichen, dass man einem Overflow> nahe kommt.
In Deinem Code teilst Du aber nicht durch 4, sondern multiplizierst
damit.
Außerdem macht es sehr wohl einen Unterschied, ob Du erst alle Zahlen
durch 4 teilst und dann aufsummierst, oder erst aufsummierst und dann
durch vier teilst (Stichwort Ungenauigkeit)...
Generell gilt: möglichst spät dividieren.
Viele Grüße
Ampfing schrieb:
> In Deinem Code teilst Du aber nicht durch 4, sondern multiplizierst> damit.
Danke, du hast natürlich recht.
> Außerdem macht es sehr wohl einen Unterschied, ob Du erst alle Zahlen> durch 4 teilst und dann aufsummierst, oder erst aufsummierst und dann> durch vier teilst (Stichwort Ungenauigkeit)...> Generell gilt: möglichst spät dividieren.
Auch hier hast du recht. Aber ab dem Wert 4 gibt es keinen Fehler mehr
der bei einer späteren Division nicht auch auftreten würden.
Und wenn mein Wertebereich von 0-20000 geht , dann hab ich einen Fehler
von 0.02%. Das sollte OK sein.
MFG
Julian Schild schrieb:
> Die Division durch 4 lässt sich einfach durch das verschieben um 2> Stellen> darstellen.
Wenn du durch 4 dividieren willst, dann schreibe auch eine Division
durch 4.
WENN diese Division auf dem Prozessor durch eine Veschiebung erreicht
werden kann UND diese Schieberei tatsächlich schneller ist als
Dividieren DANN weiß das der Compiler und ersetzt dir das auf
Assemblerebene.
Generell: Benutze immer die Operation, die die Absicht am besten
ausdrückt. An dieser Stelle ist die Absicht durch 4 zu dividieren. Also
schreib auch Division.
Bevor die Werte nun ins Array gehen werden sie bereits
> ge4telt um niemals so hohe Werte zu erreichen, dass man einem Overflow> nahe kommt.
Wozu dann der long?
Worauf ich hinaus wollte:
Bei deiner Summierung ist es völlig unerheblich ob du als
Ergebnisdatentyp einen long hast oder nicht. Bei einer Operation
betrachtet der Compiler die beiden Operanden. Nur deren Datentyp zählt
bei der Auswahl der Operation.
long i;
int j, k;
i = j + k;
j ist ein int, k ist ein int. ALso wird die Addition mit einer
int-Addition durchgeführt. Erst dieses Ergebnis wird auf long
umgewandelt.
wenn also i gleich 32765 ist und k gleich 32765, dann hast du einen
Overflow! Die Tatsache dass die Ergebnisvariable als long das richtige
Ergebnis aufnehmen könnte, ist unerheblich. Dieser Datentyp long kommt
erst dann ins Spiel, wenn das Kind (die Addition) schon in den Brunnen
gefallen ist.
@Franz:
Den Long wollte ich vorher haben. Jetzt brauch ich ihn natürlich nicht
mehr.
Danke für dein Beispiel, das war mir nicht bewusst.
Noch mal zur Genauigkeit:
Durch, dass verschieben hätte ich nur einen Fehler wenn ich ganz kleine
Werte bekomme, Werte im Bereich von 1-3.
Julian Schild schrieb:
> Noch mal zur Genauigkeit:> Durch, dass verschieben hätte ich nur einen Fehler wenn ich ganz kleine> Werte bekomme, Werte im Bereich von 1-3.
Na ja.
Du hast immer dann Fehler, wenn sich die Einzelwerte nur um wenig
unterscheiden.
200 + 201 + 202 + 203 = 806 / 4 = 201
200 / 4 + 201 / 4 + 202 / 4 + 203 / 4 = 50 + 50 + 50 + 50 = 200
wenn du damit leben kannst, ist es ok.
Auch da hast du wieder recht.
Aber es tritt wie gesagt ein max. Fehler von 0.02% auf, mit welchem ich
leben kann ;).
Noch ein mal, GROßES DANKE an dich Karl, hilfst mir immer wieder
kompetent und schnell.
Danke.