Почему SQL-запросы на Snowflake не страдают от неточностей с плавающей запятой? - PullRequest
0 голосов
/ 28 февраля 2019

Согласно документам Snowflake , FLOAT - это число с плавающей запятой IEEE 754 с двойной точностью (64 бита).Это норма.Python, например, также реализует операции с плавающей точкой и, следовательно, страдает от проблем точности с плавающей точкой при определенных значениях.Учтите, что

nRooks$ python3
Python 3.5.2 (default, Nov 12 2018, 13:43:14) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 0.3 + 0.6
0.8999999999999999

LiteSQL также дает мне значение 0.8999999999999999 для запроса select CAST(0.3 AS FLOAT) + CAST(0.6 AS FLOAT).Все как и ожидалось.

ОДНАКО , я получаю странный результат из следующего запроса на листе Snowflake:

select (0.3::float + 0.6::float)::float

Row           (0.3::FLOAT + 0.6::FLOAT)::FLOAT
1             0.9

Упрощение запроса до select 0.6 + 0.3 неизменить результат.Почему возвращается .9 вместо ожидаемого 0.8999999999999999?

1 Ответ

0 голосов
/ 04 марта 2019

Как и другие подозреваемые, это проблема форматирования текста.

Snowflake поддерживает различные способы форматирования чисел, см., Например, здесь .Таким образом, в зависимости от используемого формата, вы увидите разные значения, например:

-- Will round the value
select to_varchar(0.3::float + 0.6::float, '9.999999');
-------------------------------------------------+
 TO_VARCHAR(0.3::FLOAT + 0.6::FLOAT, '9.999999') |
-------------------------------------------------+
  0.9                                            |
-------------------------------------------------+

-- Enough decimal digits to print without rounding
select to_varchar(0.3::float + 0.6::float, '9.9999999999999999');
-----------------------------------------------------------+
 TO_VARCHAR(0.3::FLOAT + 0.6::FLOAT, '9.9999999999999999') |
-----------------------------------------------------------+
  0.8999999999999999                                       |
-----------------------------------------------------------+

-- "text minimal" format without exponent
select to_varchar(0.3::float + 0.6::float, 'tm9');
--------------------------------------------+
 TO_VARCHAR(0.3::FLOAT + 0.6::FLOAT, 'TM9') |
--------------------------------------------+
 0.8999999999999999                         |
--------------------------------------------+

-- "text minimal" format with exponent
select to_varchar(0.3::float + 0.6::float, 'tme');
--------------------------------------------+
 TO_VARCHAR(0.3::FLOAT + 0.6::FLOAT, 'TME') |
--------------------------------------------+
 8.999999999999999e-1                       |
--------------------------------------------+

Обратите внимание, что это форматирование в основном используется на стороне сервера (следовательно, явное приведение TO_VARCHAR) - разные клиенты могут форматировать плавающиезначения точек по-разному.

...