首页 > 解决方案 > 为什么 Snowflake 上的 SQL 查询不会出现浮点不准确的问题?

问题描述

根据Snowflake docs, aFLOAT是双精度(64 位)IEEE 754 浮点数。这是常态。例如,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)。一切如预期。

但是,我从雪花工作表中的以下查询中得到了一个奇怪的结果:

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

标签: sqlfloating-accuracysnowflake-cloud-data-platform

解决方案


像其他人怀疑的那样,这是一个文本格式问题。

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转换) - 不同的客户端可能会以不同的方式格式化浮点值。


推荐阅读