前言
说来实在惭愧,用spark处理hive表中的数据时,出现了两个正数相乘最后结果显示为负数后我的第一反应竟然有点懵逼,充分说明了自己在使用数据时,对Hive表中的字段类型没有进行充分的了解,当时,第二反应才想起是数据类型导致的数据超出范围了,这个还得归结在当时创建Hive表的时候,没有充分对表中每个字段要存储的数据类型进行充分调查
Java基本数据类型及范围
分类 | 数据类型 | 字节 | 取值范围 | 默认值 |
---|---|---|---|---|
布尔 | boolean | 1 | false,true | false |
整数 | 字节型byte | 1 | -128~127,即-2^7 ~ 2^7-1 | 0 |
整数 | 短整型short | 2 | -32768~32767,即-2^15 ~ 2^15-1 | 0 |
整数 | 整型int | 4 | -2147483648~2147483647,即-2^31 ~ 2^31-1 | 0 |
整数 | 长整型long | 8 | -9 223 372 036 854 775 808~9 223 372 036 854 775 807,即-2^63 ~ 2^63-1 | 0 |
字符 | char | 2 | 0~65535,\u0000 ~ \uFFFF | \u0000 |
浮点数 | 单精度浮点数float | 4 | 负数范围:-3.4028234663852886 × 10^38 ~ -1.40129846432481707 × 10^-45,正数范围:1.40129846432481707 × 10^-45~3.4028234663852886 × 10^38 | 0.0f |
浮点数 | 双精度浮点数float | 8 | 负数范围:-1.7976931348623157 × 10^308 ~ -4.94065645841246544 × 10^-324,正数范围:4.94065645841246544 × 10^1.7976931348623157 × 10^308 | 0.0 |
问题简述
- Hive表一个字段的类型
total_flow int
- 我的操作
// avg_tf是个正数
total_flow * 25 / avg_tf
-
出现的问题
通过抽查total_flow = 113716790,乘以25后为3411503700,avg_tf = 322183360,正常结果约为38,可现实结果约为-1.75… -
原因分析
int最大取值为2147438647,而现在已经达到3411503700,显然远远超过了int的取值范围,因此出现这样的原因 -
解决方案
(1)修改字段的类型为Double
(2)在计算的时候,将字段的换算成量级小一下的,防止超出范围,比如我这里给分子分母同时除以1000,或者先除后乘
后记
这里做一个简答测试:int最大值+1的结果?
public class Type_Of_Data {
public static void main(String[] args) {
int a = 2147483647;
int b = 1;
int c = a + b;
System.out.println(c);
}
}
结果:
-2147483648
为什么超过int最大范围结果成了负数?
这个和计算机如何存储二进制有关,在电脑里是以补码出现的。第一位是符号位。0为正,1为负,当正的除了符号位全为1时候,要是再加一就进位了,导致符号位为1,其他为0,再换成10进制就是你这个数了