Ich habe ein Makro #define Rechnung1 (Wert1 / Wert2) und ein weiteres #define Rechnung2 ((Wert 3 / Rechnung1)+0.5) Ziel ist es, in Rechnung2 einen Integer-Wert zu erhalten, der so genau wie möglich ist. Deshalb wird zur Rundung 0.5 addiert. Aus dem selben Grund sind Wert1 und Wert2 als Gleitkomma-Werte definiert: #define Wert1 51.0 #define Wert2 23.0 Wert3 wird zur Laufzeit bestimmt und ist ein Integer. Wird nun Rechnung2 zu einem Int-Wert führen, oder aufgrund der Tatsache, dass der Operand Rechnung1 einen Gleitkommawert beisteuert, auch einen Gleitkomma-Wert als Ergebnis ausgeben?
Mach die Makrosubstitution
1 | #define Rechnung1 (Wert1 / Wert2)
|
2 | #define Rechnung2 ((Wert 3 / Rechnung1)+0.5)
|
3 | #define Wert1 51.0
|
4 | #define Wert2 23.0
|
5 | |
6 | |
7 | |
8 | x = Rechnung2; |
Rechnung2 expandiert zu ((Wert3 / Rechnung1)+0.5) Rechnung1 expandiert zu ((Wert3 / (Wert1 / Wert2))+0.5) Wert1 und Wert2 substituieren ((Wert3 / (51.0/23.0))+0.5) Wert3 sei ein int. Dann sind die Datentypen des kompletten Ausdrucks (( int / ( double / double ) ) + double ) und jetzt wende die C-Regeln an: Welche Operation wird zuerst ausgeführt? Was ist der Datentyp des Ergebnisses? Wo wird er weiterverwendet? Was ist der Datentyp dieses Ergebnisses? Und das machst du solange weiter, bis du den kompletten Ausdruck abgearbeitet hast und den Datentyp des Ergebnisses kennst.
Zuerst (double / double), Ergebnis double. Dann (int / double), Ergebnis double. (double + double), Ergebnis double. Richtig? Würde #define Rechnung2 (int)((Wert 3 / Rechnung1)+0.5)) Abhilfe schaffen?
Wie wär's mit... #define Rechnung2 (int)(((double) Wert3 / Rechnung1)+0.5)
M. I. schrieb: > Richtig? Korrekt! (War doch gar nicht so schwer, oder?) > Würde > > #define Rechnung2 (int)((Wert 3 / Rechnung1)+0.5)) > > Abhilfe schaffen? Dann wäre das Ergebnis int. Und solange das Ergebnis positiv ist, ist es sogar korrekt kaufmännisch gerundet :-)
Nun gut, habe ich verstanden. Jetzt setzen wir mal voraus, Gleitkommaarithmetik ist nicht möglich, also die Konstanten sind auch Integer-Werte, so dass nur Integer gerechnet wird. Wie bekommt man ein möglichst genaues Ergebnis? Ich kenne die Methode, die Hälfte des Divisors auf den Dividenden zu addieren, also: #define Rechnung2 ((Wert3+Rechnung1/2)/Rechnung1) Somit wird ja das Ergebnis kaufmännisch gerundet. Gibt es noch eine genauere Möglichkeit? Z.B. "erweitern" des Bruches?
Genauer? ;) Bei Festkomma bzw. Integer? Wie das? Die Lösung mit dem Addieren der Hälfte des Divisors ist meiner Meinung nach ideal (solange der Wert im positiven Bereich bleibt).
M. I. schrieb: > Nun gut, habe ich verstanden. > > Jetzt setzen wir mal voraus, Gleitkommaarithmetik ist nicht möglich, > also die Konstanten sind auch Integer-Werte, so dass nur Integer > gerechnet wird. > > Wie bekommt man ein möglichst genaues Ergebnis? Indem man eine Grundregel beherzigt: Du willst so wenig wie möglich dividieren. Und wenn du schon dividieren musst, dann sollte das die letzte oder eine der letzten Operationen im Ausdruck sein. a/b/c und (a*c)/b können durchaus unterschiedliche Ergebnisse haben (übrigens auch bei float), obwohl sie mathematisch vollkommen äquivalent sind. > Gibt es noch eine genauere Möglichkeit? Z.B. "erweitern" des Bruches? Die genaueste Methode ist es, den ganzen Makrounsinn zu lassen, den kompletten Ausdruck zunächst mal hinzuschreiben und dann so umzuformen, dass während der Berechnung (die ja überall int Zwischenergebnisse bringt) möglichst wenig durch den Wegfall der Nachkommastellen auf der Strecke bleibt. Dabei aber auch im Auge behalten, dass kein Zwischenergebnis den int-Zahlenbereich überschreiten darf.
>Genauer? ;) Bei Festkomma bzw. Integer? Wie das?
Nunja, man könnte ja alle Rechnungen mit dem Faktor 100 beaufschlagen,
so dass zwei Nachkommastellen nicht abgeschnitten werden und im Ergebnis
erhalten bleiben. Erst bei der letzten Rechnung wird dann durch den
Faktor geteilt. Man muss natürlich darauf achten, dass die Werte nicht
zu groß für den Typ werden. Ob das letztlich genauer ist als die andere
Methode, weiß ich nicht.
M. I. schrieb: >>Genauer? ;) Bei Festkomma bzw. Integer? Wie das? > > Nunja, man könnte ja alle Rechnungen mit dem Faktor 100 beaufschlagen, > so dass zwei Nachkommastellen nicht abgeschnitten werden und im Ergebnis > erhalten bleiben. Ja klar, einfach das Festkomma verschieben, aber beim Runden kann man nichts genauer machen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.