wie Gleitkomma umgehen??

OP #2391555
Lesenswert?

Ich möchte folgende Formel:

float preis;
preis =   (VorKomma + NachKomma/100) * 10,6381 * 0,0649;

nicht mehr als Gleitkomma berechnen, da es so viel speicher frisst. Ich 
habe aber grad voll den Faden verloren, wie man das dann ohne Gleitkomma 
machen kann. Der Wert VorKomma kann bis 999.999 gehen. Mit dem Wert aus 
NachKomma ergibt sich eine Zahl mit 99.999.999. Das würde ja noch gehen 
aber mit der der Multiplikation mit 10.6381 (damit es keine Kommas mehr 
gibt) kommt eine doch recth große Zahl raus. Ich stehe auf dem Schlauch.

PS: Umrechnung des Gaszählerstandes (m³) in Euro

Danke!
Gast #2392213
Lesenswert?

Tino Kühn schrieb:
> Der Wert VorKomma kann bis 999.999 gehen.

Soll das heissen, der m³ Gas kostet bis zu 1 Mio Euro, oder beziehst du 
1 Mio m³? Du solltest bei Festkommaberechnungen erst mal prüfen, welche 
Zahlen überhaupt vorkommen können. Ausserdem ist eine Preisangabe in 
Euro mit 4 Nachkommastellen nicht sinnvoll.

Gruss Reinhard
Moderator (Firma: Titel) Persönliche Seite #2392353
Lesenswert?

Tino Kühn schrieb:
> Das würde ja noch gehen
> aber mit der der Multiplikation mit 10.6381 (damit es keine Kommas mehr
> gibt) kommt eine doch recth große Zahl raus. Ich stehe auf dem Schlauch.
Lustigerweise brauchst du entweder die Genauigkeit oder die Dynamik 
nicht. Denn eine float Zahl hat auch nur 6 signifikante Stellen!

> PS: Umrechnung des Gaszählerstandes (m³) in Euro
Euro? Geld? Abrechnung?
Siehe dort ab Abschnitt 7.6.5:
http://www.win-tux.de/c_007_005.htm#RxxobKap0070050400263A1F0121BA
1
Der Typ float ist also ungeeignet für kaufmännische und genaue wissenschaftliche Berechnungen.
;-)
OP #2392567
Lesenswert?

Danke für die Zuschriften!
Der Gaszähler kann bis 999999,999 Zählen. Die Einheit ist m³. Dies wird 
per Faktor 10,6381 in kWh umgerechnet. Der Faktor wird von den Gaswerken 
vorgegeben. Dann wird noch mit dem aktuelle Gaspreis von 0,0649 €/kwh 
multipliziert und fertig ist der Gesamtpreis oder wenn nur die delta-m³ 
gezählt werden der Zykluswert. Daher kommen die ominösen Faktoren. OK, 
das float nur 6 Nachkommastellen hat wußte ich nicht. Double macht das 
auch nicht besser, da der Mega8 30% nur durch das Einfügen der Doubl 
Variable verliert.

preis=((uint32_t)(100*VorKomma+NachKomma)*115832) shift right 24

ich glaube das geht auch nicht. Der jetzige Zählerstand ist knapp 25000 
und wenn ich das einsetze dann kommt eine Zahl größer als 32 bit raus. 
So ganz ist mir das alle snoch nicht klar...
Moderator (Firma: Titel) Persönliche Seite #2392772
Lesenswert?

Tino Kühn schrieb:
> OK, das float nur 6 Nachkommastellen hat wußte ich nicht.
Es geht nicht um Nachkommastellen, sondern du hast nur 6 
signifikante Stellen. Du kannst also eine Zahl wie 123456,7 nicht mehr 
zuverlässig darstellen, denn die 6 signifikanten Stellen sind schon in 
den Vorkommastellen verbraten...  :-o

Tino Kühn schrieb:
> Der Gaszähler kann bis 999999,999 Zählen.
Ändert sich also.
> Dann wird noch mit dem aktuelle Gaspreis von 0,0649 €/kwh multipliziert
Und der sowieso...
> Dies wird in kWh umgerechnet. Der Faktor wird ... vorgegeben.
Kann sich der auch ändern: andere Gasqualität, anderer Faktor?

Damit bleibt dir nichts anderes, als den vorgeschlagenen uint64 zu 
nehmen und in möglichst kleinen Einheiten zu rechnen, damit die Zahlen 
als Ganzzahl dastehen (also z.B. statt 0,0649 €/kwh in 
649centicent/kwh).
#2392788
Lesenswert?

Warum machst du dir das Leben unnötig schwer indem du erst die riesigen 
Absolutzahlen umrechnest. Dich interessiert nur der Verbrauch, also ERST 
die Differenz aus den Zählerständen, damit ist deine Zahl 
realistigerweise schon mal deutlich kleiner als 6 Stellen.
Wenn du beliebig genau rechnen willst, dann solltest du dir BCD codierte 
(bei µC ggf. gepackt codierte) Zahlen anschauen. Algorithmen für die 
Grundrechenarten findet man garantiert im Netz, ansonsten ist das eine 
gute Übung.
#2392914
Lesenswert?

Realistischerweise ist der Zählerstand vielleicht um eine Größenordnung 
größer als die Differenzen, er läuft ja nicht seit der Jungsteinzeit ;). 
Man spart sich also nicht viel indem man mit Differenzen rechnet.

Ich würde das oben erwähnte Verfahren auf einen 32bit shift aufblasen, 
dann sollte man mit den signifikanten Stellen einigermaßen auskommen.

1
#define faktor (uint32_t)((10,6381 * 0,0649 * 4294967296) + 0,5) // ~2,97e9
2

3
zaehlerstand_100 = (100 * vorkomma) + nachkomma;
4

5
preis_cent = (uint64_t)(zaehlerstand_100 * faktor ) >> 32;

Technisch gesehen erscheint es bizarr wegen so einem Problem mit einem 
64bit Integer zu rechnen, immerhin dürfte die Genauigkeit des Zählers um 
Größenordnungen schlechter sein, aber der Buchhaltung wird es trotzdem 
auffallen wenn man es nicht macht.

Gruß,
Reinhard

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren