userreading difference rechnet falsch? zu viele Nachkommastellen.

Begonnen von Frank_Huber, 24 November 2020, 09:07:48

Vorheriges Thema - Nächstes Thema

Frank_Huber

Moin Moin,

Hab mir das ESP32-Cam Modul wie im Thread hier beschrieben aufgebaut und per MQTT eingebunden.
soweit so gut.

Als nächsten Schritt habe ich mir ein User-Reading mit "difference" angelegt welches auch m³ in l umrechnet. attr Wasseruhr userReadings Verbrauch difference {ReadingsNum($NAME,"qm",0) * 1000}
Auch das funktioniert generell, rechnet aber falsch. d.h. es macht zuviele Nachkommastellen.

Beispiel:
Wert alt: 286.1347
Wert neu: 286.1420
"difference": 7.29999999998836

da sollte doch eigentlich 7.3 rauskommen. Wie kommt FHEM da auf die 7.29999999998836 ???
Ich weis, ich kann das über ein zweites User-Reading noch runden lassen, mich würde aber auch interessieren wo das herkommt und ob sich die Berechnung nicht auch korrigieren lässt ohne zweites UR?

gesamtes List:
Internals:
   CID        wasser
   DEF        wasser
   DEVICETOPIC Wasseruhr
   FUUID      5fb7962a-f33f-c13c-0803-ec456e7af3161d23
   IODev      MQTT2_SERVER
   LASTInputDev MQTT2_SERVER
   MQTT2_SERVER_MSGCNT 124
   MQTT2_SERVER_TIME 2020-11-24 09:00:07
   MSGCNT     124
   NAME       Wasseruhr
   NR         369
   STATE      286.1 m³
   TYPE       MQTT2_DEVICE
   .attraggr:
   .attrminint:
   .userReadings:
     HASH(0x62c69c0)
   Helper:
     DBLOG:
       Verbrauch:
         logdb:
           TIME       1606204807.8506
           VALUE      0
       l:
         logdb:
           TIME       1606125982.4683
           VALUE      286029.1
       qm:
         logdb:
           TIME       1606204807.8506
           VALUE      286.1420
   OLDREADINGS:
   READINGS:
     2020-11-24 09:00:07   Verbrauch       0
     2020-11-24 09:00:07   qm              286.1420
Attributes:
   DbLogExclude .*
   DbLogInclude qm,Verbrauch
   IODev      MQTT2_SERVER
   group      Zähler
   readingList wasser:watermeter/qm:.* qm
   room       _HSA
   stateFormat {sprintf("%.1f"." m³",ReadingsNum("Wasseruhr","qm",0))}
   userReadings Verbrauch difference {ReadingsNum($NAME,"qm",0) * 1000}


Danke & Grüße
Frank


Otto123

Hallo Frank,

Gleitkommarechnung ist a priori nicht "exakt". Da wird es in vielen Fällen zu vielen Kommastellen kommen. Da ist nicht FHEM dran Schuld :)

Und Du hast in dem Konstrukt zweimal die Gleitkomma Rechnung: einmal {die Rechnung in perl} und außen die difference.
Ich denke es bleibt nur die Rundung im zweiten Reading

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Frank_Huber

Danke Otto,

Aber warum nutzt FHEM bzw Perl dann so ungenaue Rechenmethoden?
Das erzeugt doch imho mehr Aufwand als Nutzen.
Oder gibt es keine Alternativen?

Grüße
Frank

Otto123

Das hat nichts mit genau oder ungenau zu tun, das ist mMn eine Frage der internen Zahlendarstellung
Wenn du "difference": 7.29999999998836 auf vier Stellen hinter dem Komma rundest (wie deine Ausgangszahlen) dann ist das Ergebnis doch genau.  ;)

Du musst mal ein bisschen zu binärer Gleitkomma Arithmetik lesen. Beispiel
Ich glaube die zweite Folie erklärt es ganz gut.
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Frank_Huber

Die Ausgangsdaten haben sogar nur eine Stelle hinterm Komma (auf l umgerechnet)
Danke für den Link. Das erklärt warum es falsch dargestellt wird. :-)

Was ich aber noch nicht ganz verstehe ist warum Perl / FHEM auf diese Weise rechnet?
Gibt es da in Perl keine besseren Wege?

Damian

Zitat von: Frank_Huber am 24 November 2020, 14:19:07
Die Ausgangsdaten haben sogar nur eine Stelle hinterm Komma (auf l umgerechnet)
Danke für den Link. Das erklärt warum es falsch dargestellt wird. :-)

Was ich aber noch nicht ganz verstehe ist warum Perl / FHEM auf diese Weise rechnet?
Gibt es da in Perl keine besseren Wege?

In höheren Programmiersprachen ist es nichts besonders.

Taschenrechner haben dagegen eine Genauigkeit, die höher ist als die Anzahl der dargestellten Nachkommastellen, durch entsprechendes Runden fallen solche Sachen nicht auf:

(1/3)*3 ist dort meistens wieder 1 ;)
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF