MySQL中实现Java Double.doubleToLongBits等效功能的方法咨询
解决方案
错误原因
你之前使用CONV函数直接转换浮点数的方法不可行:CONV仅支持整数类型的进制转换,输入浮点数时会自动截断小数部分,你两次尝试实际处理的都是整数-58,因此结果不符合预期。
实现Double.doubleToLongBits同等效果
MySQL没有直接内置对应函数,可以通过进制转换加有符号数修正实现,直接执行以下查询即可得到目标结果:
SELECT CASE WHEN CONV(HEX(CAST(-58.725 AS DOUBLE)), 16, 10) >= 9223372036854775808 THEN CONV(HEX(CAST(-58.725 AS DOUBLE)), 16, 10) - 18446744073709551616 ELSE CONV(HEX(CAST(-58.725 AS DOUBLE)), 16, 10) END AS double_to_long_bits;
封装为自定义函数(可选)
如果需要频繁调用,可以创建自定义函数简化操作:
DELIMITER // CREATE FUNCTION DoubleToLongBits(input_double DOUBLE) RETURNS BIGINT DETERMINISTIC BEGIN DECLARE hex_ieee CHAR(16); DECLARE unsigned_num DECIMAL(20); SET hex_ieee = HEX(CAST(input_double AS DOUBLE)); SET unsigned_num = CONV(hex_ieee, 16, 10); -- 64位无符号转有符号处理 IF unsigned_num >= 9223372036854775808 THEN RETURN unsigned_num - 18446744073709551616; ELSE RETURN unsigned_num; END IF; END // DELIMITER ;
创建完成后直接调用即可:
SELECT DoubleToLongBits(-58.725);
返回结果为-4589910410541609779,和Java方法返回值完全一致。
提取指数、有效数方法
拿到对应的64位有符号整数后,按IEEE 754双精度规则按位拆分即可:
- 符号位:将结果右移63位,值为1表示负数,0表示正数
- 指数值:将结果右移52位后与
0x7FF做按位与运算,得到的结果减去偏移量1023就是实际指数 - 有效数(尾数):将结果与
0xFFFFFFFFFFFFF做按位与运算,加上隐含的高位1就是完整的有效数
如果是处理FLOAT单精度数值,逻辑类似:将CAST目标改为FLOAT,HEX得到8位十六进制值,32位无符号转有符号时大于2147483648就减去4294967296,指数偏移量改为127,尾数长度为23位即可。
内容的提问来源于stack exchange,提问作者keesjanbertus
相关产品推荐
相关产品推荐

