Probier mal Wert*10000/65536, das ist rundungstechnisch auf jeden Fall besser.
Ohne Code ist es schwierig was zu sagen, aber bist du dir sicher, dass der Compiler bei der Rechnung auch intern Floats benutzt? Ich mir nämlich nicht
mfg
Hallo zusammen,
ich habe einen Integer Wert, der den Bereich -255 bis 255 abdecken sollte. Der Wert soll sich aus folgender Rechnung ergeben:
(100/65536)* wert * 100;
Nun wird da ja eine Zahl raus kommen, die nicht in ein Integer passt, ich bin davon ausgegangen, dass die Nachkommastellen einfach weggelassen werden. Es kommt aber immer 0 raus?
Probier mal Wert*10000/65536, das ist rundungstechnisch auf jeden Fall besser.
Ohne Code ist es schwierig was zu sagen, aber bist du dir sicher, dass der Compiler bei der Rechnung auch intern Floats benutzt? Ich mir nämlich nicht
mfg
Die Division durch 65536 ist das Problem, denn der Compiler interpretiert alle Werte als Integer (es sei denn, wert ist ein float).
Eine mögliche Lösung sähe so aus:
Es gibt aber auch noch eine etwas elegantere Lösung, wenn man die Reihenfolge geringfügig ändert:Code:(int)((100.0f / 65536.0f) * (float)wert * 100.0f); oder (int)(((float)100 / (float)65536) * (float)wert * (float)100);
Hier habe ich die rechenintensive Division durch einen einfachen Rechtsshift ersetzt, der wesentlich schneller ist (geht immer, wenn man durch 2^n dividieren möchte). Wichtig dabei ist aber, daß die Multiplikation vorher erfolgt, denn sonst entsteht wieder das selbe Problem wie bei deiner Variante.Code:(100 * 100 * wert) >> 16; bzw. (10000 * wert) >> 16;
So viele Treppen und so wenig Zeit!
100/65536 = 0 .... die nachkommazahlen werden abgeschnitten!
und alles multipliziert mit null bleibt null ^^
stell es doch ein wenig um, erst alles multiplizieren und DANN dividieren, aber achtung, pass auf dass bei dem multiplizieren der wert nicht überläuft!
Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
nicht.
Damit es beim Multiplizieren keinen Überlauf gibt kann man die Berechnung mit 32 Bit Zahler erzwischen, indem man die Konstante 10000 als 10000L schreibt und so zu einem Long wert macht.
wenn man auf den Zahlenbereich achtet, sollte man sich den Rechenvorteil der Prozessorarchitektur nicht durch Verwendung von long Werten zunichte machen finde ich, außerdem habe ich vergessen zu erwähnen, dass man am besten einen expliziten cast auf (signed int) der Formel voranstellt, damit der compiler auch das Vorzeichen mitnimmt!
Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
nicht.
Um eine Rechnung mit 32 Bit kommt man in C kaum herum:
Wenn das Ergebnis bis 255 gehen kann, passt das Ergebnis * 65536 gerade nicht mehr in 24 Bit, und schon gar nicht in 16 Bits.
In die 24 Bit würde man es gerade noch bekommen indem man
((25*25)*wert) / (4096) rechnet.
Aber 24 Bit Zahlen werden von GCC, wie fast allem C Compilern nicht unterstützt, das hilft einem also auch nicht weiter. Genauso fehlt die Multiplication 16 Bit * 16 Bit -> 32 Bit oder besser noch nach 24 Bit.
ACHTUNG: Bei vorzeichenbehafteten Zahlen funktioniert der Rechtsshift nur in bestimmten Situationen (Vielfache von , da er NICHT zur Null hin rundet. Beispiel (für 3-Bit-Integer):
Allerdings kann man den entstehenden Fehler auch ausbügeln (in diesem Beispiel durch eine Addition von 1)Code:-1 >> 1 = -1 // Falsch -2 >> 1 = -1 -3 >> 1 = -2 // Falsch -4 >> 1 = -2
mfG
Markus
Dieser Unsinn ist wohl auch einfach nicht totzukriegen.
Eine solche Simpelst-Optimierung macht natürlich auch der Compiler selber. Du gewinnst mit dieser Schreibweise also rein gar nichts. Du verlierst nur etwas, nämlich die Offensichtlichkeit der eigentlichen Absicht hinter dem Code.
Also: wenn du eigentlich dividieren willst, dann benutze '/', und wenn du schieben willst, dann benutze '>>'. Das Eine durch das Andere zu ersetzen, weil es schneller ist (es gibt übrigens auch Prozessoren, wo die Division schneller ist), kannst du getrost dem Compiler überlassen.
MfG
Stefan
moin moin,
warum so viel Aufwand?
(100/65536)* wert * 100 -->> das ist doch 1Byte * ~1,52...
Ich würde da eine kleine Tabelle nehmen, es sind 256 Werte zu 16Bit notwendig.
so:
ausWert = Tabelle[abs(einWert)]
if Signum(einWert) then ausWert = - ausWert
Warum soll da überhaupt was umgerechnet werden, was ist der Hintergrunf?
Mit Gruß
Peter
Lesezeichen