Makro Gleitkomma/Integer

OP #1414881
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?
#1414891
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.
#1414947
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 :-)
OP #1414955
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?
#1414964
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.
OP #1414967
>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.
Persönliche Seite #1415010
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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.