home-assistant / core

:house_with_garden: Open source home automation that puts local control and privacy first.
https://www.home-assistant.io
Apache License 2.0
72.91k stars 30.52k forks source link

Floating point approximation #24572

Closed Shulyaka closed 5 years ago

Shulyaka commented 5 years ago

Home Assistant release with the issue:

0.94.3

Last working Home Assistant release (if known): N/A

Operating environment (Hass.io/Docker/Windows/etc.):

Python 3.6.0 armv7l GNU/Linux

Component/platform:

Both Lovelace and States

Description of problem: Some sensors display values with error caused by floating point rounding. For example: "24.600000000000001 °C", "55.299999999999997 %", "166.24000000000001 m³"

Problem-relevant configuration.yaml entries and (fill out even if it seems unimportant):

frontend:

Traceback (if applicable): N/A

Additional information:

Shulyaka commented 5 years ago

Not sure if it is a HA or frontend issue, but I raised it here since it happens on both Lovelace and States UI. I can move it to the home-assistant-polymer project if you want

OttoWinter commented 5 years ago

frontend only receives state as a text string.

Please report the integrations with these issues - it's not a frontend issue.

Shulyaka commented 5 years ago

Well, I noticed the issue with zha, REST sensor, lufdaten and openuv platforms

Shulyaka commented 5 years ago

I think the issue is best demonstrated with Templates editor. The default testing template defines my_test_json with "temperature" set to 25. Change that to 25.1 and you will see the difference:

Template

{% set my_test_json = {
  "temperature": 25,
  "unit": "°C"
} %}

The temperature is {{ my_test_json.temperature }} {{ my_test_json.unit }}.

produces

The temperature is 25 °C.

And template

{% set my_test_json = {
  "temperature": 25.1,
  "unit": "°C"
} %}

The temperature is {{ my_test_json.temperature }} {{ my_test_json.unit }}.

produces

The temperature is 25.100000000000001 °C.
OttoWinter commented 5 years ago

It's still the integration's responsibility to round values.

It's correct that templates do not round values, but that's the expected behavioe because the string you posted is the correct string representation of the given floating point number.

You need to explicitly round it with a jinja2 round method.

As I said, the state frontend only receives textual data; the integrations in question need to be updated to eound values properly. For that please post more infos about your setup.

Shulyaka commented 5 years ago

{{ my_test_json.temperature | round (2) }} produces same output (not rounded) because the result of round is still float. { "%.2f" | format(my_test_json.temperature) }} does produce 25.10 but I'm worried that it is a string, not a number.

I will try to create a minimal example with a template sensor.

OttoWinter commented 5 years ago

but I'm worried that it is a string, not a number.

It is a string, but that's kinda the point. There are just some numbers (like 25.1) that cannot be represented well as floating poinr numbers.

I will try to create a minimal example with a template sensor.

Again, templates (and template sensor) only create text output. What you define in the template (and any float to string rounding) is what you will get.

Shulyaka commented 5 years ago

Okay, I guess I need to raise that to jinja2 that its float to string conversion is not always human-readable.

Well, here is another example:

luftdaten:
  sensor_id: 22633
  show_on_map: true
  sensors:
    monitored_conditions:
      - temperature
      - humidity

That gives me 34.899999999999999 °C for temperature and 30.699999999999999 % for humidity right now.

Shulyaka commented 5 years ago

Well, probably it is a python-specific issue for my platform.

Python 3.6.0 (default, Jan 14 2019, 16:14:11)
[GCC 4.8.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 25.1
25.100000000000001

On x86_64 I have a different result:

Python 3.7.3 (default, May 11 2019, 00:38:04)
[GCC 9.1.1 20190503 (Red Hat 9.1.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 25.1
25.1
Adminiuga commented 5 years ago

what linux is this? can't reproduce issue with Debian Buster on arm7l platform

ha@hostname:/$ uname -a
Linux xu4 5.1.15-odroidxu4 #5.89 SMP PREEMPT Tue Jun 25 21:24:03 CEST 2019 armv7l GNU/Linux
ha@hostname:/$ python3
Python 3.7.3 (default, Apr  3 2019, 05:39:12) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 25.1
25.1
>>> 26.1
26.1
>>> 24.6
24.6
>>> 55.2
55.2
>>> 55.29
55.29
>>> 55.299
55.299
>>> 

Not sure what linux distribution you are running, but consider upgrading.

Shulyaka commented 5 years ago

That's Turris Omnia (OpenWRT-based).

root@shulyaka:~# uname -a
Linux shulyaka.org.ru 4.4.182-a890a5a94ebb621f8f1720c24d12fef1-0 #1 SMP Wed Jun 19 01:02:05 CEST 2019 armv7l GNU/Linux
root@shulyaka:~# python3 --version
Python 3.6.0
Shulyaka commented 5 years ago

Closing issue for now. Will try to resolve it on python level, will reopen if I fail.