图片由夸克AI绘制
最近在写一个Hive SQL的时候遇到了除法结果不对的问题。大概就是sum(a)/sum(b)明明不等于0但是SQL返回的结果是0的问题。
这个问题对我来说真的是第一次遇到,老司机们对此的评价是:你没有系统学过编程。
因为 Hive 的表达式计算遵循 Java 的整数除法规则,在 Java 中,两个整数相除结果还是整数, Hive 的行为和Java一致。
在 Java/Hive 中,/ 运算符的行为取决于操作数的类型:如果两个操作数都是 int、long 等整数类型,执行的是整数除法,结果会被截断;如果其中至少一个操作数是 float 或 double,则执行的是浮点除法,保留小数部分。
因此这个问题有两种解法,一个解法是给分子或者分母乘上一个浮点数让小数点能够正常显示,另一个解法是在除法之前先对数据格式进行调整:
SELECT
SUM(a) AS sum_a,
SUM(b) AS sum_b,
SUM(a) * 1.0 / SUM(b) AS ratio
FROM your_table;
“整数除法截断”并不是 Hive/Java 的专利,而是一种历史沿袭下来的“C 家族”语义——只要两个操作数都是整数类型,除法结果就向 0 截断(truncate toward zero)。目前主流语言里,只要没有显式浮点参与,就极有可能掉进这个坑里面。
C/Java/C++/Go/Rust/Kotlin/Scala/Python2等语言都有这个问题,不过也好记,只要这门语言把“/”同时用于整数和浮点,就大概率会采用 C 语义:整数÷整数→向 0 截断。想要避免,要么把其中一个操作数变成浮点,要么用专门的“真除法”运算符。
又是有用的知识增加的一天。