Problem with Math in Blockly

  • Platform information:
    • Hardware: VMWare on HP Server
    • OS: Linux 24.04
    • Java Runtime Environment: Zulu17.56
    • openHAB version: 4.3.4
  • Issue of the topic: if i try to calculate with Blockly, there ist a problem with decimal Numbers

I created now two rules with Blockly, which do simple calculations but i get always a
wrong result: “0.00000000000001” is missing in to reasult.

First time, numbers came from different items (max. 2 decimal numbers) Second time i just try to get sum from influxBD:

The rule in textual definition is working correctly.

Any Ideas where i can search for the Problem?

You need to provide much more information.

What’s an example the value being added to 1e-14?

Show the code this blockly compiles to (icon in the bottom right).

What language did you use for the “textual definition” where it works?

How are you checking whether the 1e-14 was added to the number to verify the result?

Note that the usual way that programming languages represent numbers have limitiations where there are as many numbers that simply cannot be represented as there are numbers that can be exactly represented. And the higher the precision (i.e. more decimal places) the more likely you are to encounter a number that cannot be represented. In those cases where it cannot represent the number, it gets as close as it can. But “as close as it can” is usually at like 6 decimal places, not 14. So it could be possible that working with numbers at such high precision is not feasible in JS (which is what blockly compiles to) but Rules DSL (which uses BigDecimal) might since it uses a different way to represent floating point numbers which has support for better precision.

Thank you for the fast answer. I already deltete the rule above, but i have another example (Calculating the Daily kWh of House), which i guess, the problem should be more clear:

Code:

var Akku_Use, Line_Import, Solar_Akku, Solar_Export, SolarSum, Verbrauch, NegVerbrauch, Solar_Eigenverbrauch, VerbrauchSum;


Akku_Use = items.getItem('SA_HTTP_Enpalbox_Battery_Entladung_Tag').state;
Line_Import = items.getItem('SA_HTTP_Enpalbox_WR_Import_Daily_Total').state;
Solar_Akku = items.getItem('SA_HTTP_Enpalbox_Battery_Ladung_Tag').state;
Solar_Export = items.getItem('SA_HTTP_Enpalbox_WR_Export_Daily_Total').state;
SolarSum = items.getItem('SA_HTTP_Enpalbox_WR_Prod_Daily_Total').state;
Verbrauch = parseFloat(Line_Import) + parseFloat(Akku_Use);
NegVerbrauch = parseFloat(Solar_Akku) + parseFloat(Solar_Export);
Solar_Eigenverbrauch = parseFloat(SolarSum) - parseFloat(NegVerbrauch);
VerbrauchSum = parseFloat(Solar_Eigenverbrauch) + parseFloat(Verbrauch);
items.getItem('F_Haus_Berechnung_Stromverbrauch').sendCommand(VerbrauchSum);
console.info(Akku_Use);
console.info(Line_Import);
console.info(Solar_Akku);
console.info(Solar_Export);
console.info(SolarSum);
console.info(Verbrauch);
console.info(NegVerbrauch);
console.info(Solar_Eigenverbrauch);
console.info(VerbrauchSum);

As you see, i log all the Variables, which seams to be correct, but “Solar_Eigenverbrauch” is wrong:

2025-05-20 13:04:41.514 [INFO ] [nhab.automation.script.ui.bc0429db36] - 4.6
2025-05-20 13:04:41.515 [INFO ] [nhab.automation.script.ui.bc0429db36] - 0.4
2025-05-20 13:04:41.516 [INFO ] [nhab.automation.script.ui.bc0429db36] - 7.8
2025-05-20 13:04:41.516 [INFO ] [nhab.automation.script.ui.bc0429db36] - 13
2025-05-20 13:04:41.516 [INFO ] [nhab.automation.script.ui.bc0429db36] - 28
2025-05-20 13:04:41.517 [INFO ] [nhab.automation.script.ui.bc0429db36] - 5
2025-05-20 13:04:41.517 [INFO ] [nhab.automation.script.ui.bc0429db36] - 20.8
2025-05-20 13:04:41.518 [INFO ] [nhab.automation.script.ui.bc0429db36] - 7.199999999999999
2025-05-20 13:04:41.518 [INFO ] [nhab.automation.script.ui.bc0429db36] - 12.2

The first problem I see is you are trying to do math with the plain state of the Item. The plain state is always a String, never a number. You need to use the “get numeric state of item” block.

Screenshot 2025-05-20 at 7.07.23 AM

If these Items had units, you would use the quantity state.
That would at least avoid the parseFloats that have been added. Beyond that (28 - 20.8) = 7.2 but if I recall correctly, 7.2 is one of those numbers that cannot be exactly reprecented using IEEE 754 notation which is what JS uses. So it gets as close as it can, which in this case is 7.199999999999999.

The dirty secret of programming is when dealing with floating point numbers you almost never get the exact correct answer. It’s almost always going to be just close enough. That’s one reason why you should almost never test a floating point number for ==. Two floating point number that seem like they should be the exact same almost never are.

This isn’t a problem with BigDecimal which is the Java class that Rules DSL uses to do math with because it doesn’t use IEEE 754 but some other representation to get higher precision (i.e. fewer numbers that cannot be represented).

Consider these lines:

console.log((28-20.7));
console.log((28-20.8));
console.log((28-20.9));

They produce the following logs:

2025-05-20 07:26:14.105 [INFO ] [nhab.automation.script.ui.scratchpad] - 7.300000000000001
2025-05-20 07:26:14.106 [INFO ] [nhab.automation.script.ui.scratchpad] - 7.199999999999999
2025-05-20 07:26:14.107 [INFO ] [nhab.automation.script.ui.scratchpad] - 7.100000000000001

tl;dr: Nothing is wrong here, computers are just bad at floating point numbers, particularly when you take two floating point numbers and do math with them.

1 Like