<Issue> Hive 中的浮点数据类型



初始数据:

CREATE TABLE `test.test_data`(
user VARCHAR(10),
amount FLOAT) 
TBLPROPERTIES ('transactional'='true');
INSERT INTO `test.test_data`
SELECT 'sonnh', 300000000000
UNION ALL
SELECT 'sonnh1', 1000000000000
UNION ALL
SELECT 'sonnh2', 900000000000;

获取数据:

SELECT * FROM `test.test_data`

结果:

test.test_data.user    test.test_data.amount
sonnh                  299999986000
sonnh1                 1000000000000
sonnh2                 899999990000

我在使用如上所述的浮点数据类型时遇到了一个问题。有人给我解释一下。

我认为这可以追溯到配置单元存储浮点、双精度和小数的基本原理。

  • 十进制-根据文档-配置单元存储精确的数值。但实际上,蜂箱存储几乎接近实际值,或者如果实际值超过规模、精度,则为空
  • Double(8字节,双精度(和Float(4字节,单精度(-两者都是浮点数字,存储非常接近的数值近似值。所以,如果它必须存储更高范围的东西,近似就不能正常工作。它可以存储大约从-10^308到10^308

因此,如果您需要财务应用程序,最好使用十进制,如果您不关心舍入问题,则使用浮点或双精度。

以下是对上述三种数据类型的实验。

CREATE TABLE tmp(   a string,     f FLOAT,    db double,    dc decimal(5,4)    )  ;
insert into tmp SELECT 'id', 900000000000000000,900000000000000000,123.123 ;
insert into tmp SELECT 'id', 90000000,99900000000000000000,99.999 ;
insert into tmp SELECT 'id', 99123.456,9000000123.456,9.9999999 ;
insert into tmp SELECT 'id', 9999999123.456,500000,123.123 ;
insert into tmp SELECT 'id', 9999999000.456,99900000000000000000999999999999999.12349,9990.099999 ;
insert into tmp SELECT 'id', 9999999000.456,9990000000000000000099999999999.12349,90.999 ;

select * from tmp;
tmp.a   tmp.f               tmp.db                      tmp.dc  
id      900000020000000000  900000000000000000          123.12300   -- notice that float column cant handle the data and showing different data.
id      90000000            99900000000000000000        99.99900    -- everything is fine because they are within range.
id      99123.45            9000000123.456              10.00000    -- decimal approximated the data to 10 which is very close to actual value.
id      9999999000          500000                      123.12300   --all good
id      9999999000          9.99e+34                    NULL        --Decimal put null because it cant handle the data. Double approximated the data to E34. 
id      9999999000          9.99e+30                    90.99900    --Decimal is good because data is within range. Double approximated the data to E34.