【发布时间】:2020-11-09 19:37:32
【问题描述】:
select 52 * 20 / 6700000 ;
=0.00015522388059701492
select cast(52 as decimal(2,0)) * 20 / 6700000;
=0.00015522
为什么使用小数会破坏精度? 使用精度更高的小数或将查询的所有成员转换为小数都没有帮助,结果将仅保持 8 位精度。
【问题讨论】:
select 52 * 20 / 6700000 ;
=0.00015522388059701492
select cast(52 as decimal(2,0)) * 20 / 6700000;
=0.00015522
为什么使用小数会破坏精度? 使用精度更高的小数或将查询的所有成员转换为小数都没有帮助,结果将仅保持 8 位精度。
【问题讨论】:
在处理浮点数时,计算机必须在速度和精度之间找到折衷方案。这在处理非常小或非常大的浮点数时尤其明显。
有一个IEEE standard on how languages should treat floating point numbers,所以这个错误在某种程度上是“标准化的”。
这是一个有趣的例子,比较多种语言:https://0.30000000000000004.com/
当您告诉程序不要将某事物视为浮点数而是将其视为小数时,结果会发生变化,因为它不再符合标准。
【讨论】:
在情况 1 中,hive 返回 double,因此您会看到非常大的精度。十进制类型的范围大约是 -10^-308 到 10^308。
select 52 * 20 / 6700000 ;
Returning Hive schema: Schema(fieldSchemas:[FieldSchema(name:_c0, type:double, comment:null)], properties:null)
在情况 2 中,hive 返回 decimal(12,8) 所以你会看到这样的结果。
select cast(52 as decimal(2,0)) * 20 / 6700000;
Returning Hive schema: Schema(fieldSchemas:[FieldSchema(name:_c0, type:decimal(12,8), comment:null)], properties:null)
为什么?我不是 100% 确定,但我认为在情况 1 中,hive 正在尝试返回默认数据类型,但在情况 2 中,因为我们使用强制转换十进制,所以它试图以十进制(12,8)返回。我运行 SQL 并捕获内部日志以显示返回数据类型。
【讨论】: