long转double在≤9007199254740992L时100%精确,百万至万亿级均安全;超限时应优先保持long运算,必要时用BigDecimal(String)中转并验证(long)d==l。

Java中long转double时,百万级数值本身不会畸变——真正出问题的是超过约900万亿(2⁵³)的大数。比如9007199254740993L转double后变成9007199254740992.0,差了1。百万级(10⁶)、甚至十亿级(10⁹)、万亿级(10¹²)都远在安全范围内,完全不会丢精度。所谓“百万级大数精度畸变”,通常是误判或混淆了数量级。
先确认你的数到底有多大
别凭感觉说“很大”,直接看数字位数或用数学边界判断:
- 2⁵³ = 9,007,199,254,740,992 ≈ 9千万亿(16位数)
- 只要你的long值绝对值 ≤ 9007199254740992L,转double就100%精确
- 100万是10⁶(7位),1亿是10⁸(9位),1千亿是10¹¹(12位)——全在安全区
- 如果你的数是时间戳(如System.currentTimeMillis(),当前约17亿),它只有10位,完全安全
真超了2⁵³?优先不转double
如果业务确实涉及超大整数(比如分布式ID、天文计数、超长序列号),且后续要参与计算或比较,最稳妥的方式是避免转double:
- 保持用long做加减、比较、存储——整数运算无损
- 显示或日志中需要小数形式?用String.format("%.0f", (double)val)仅作展示,不用于计算
- API返回或JSON序列化时,确保框架不自动把long转成double(如Fastjson需配置SerializeConfig.useBigDecimalForLong = true)
必须用double参与计算?走BigDecimal中转
仅当算法强制要求double输入(如某些数学库、绘图坐标、归一化处理),且你无法改接口时,才用BigDecimal过渡:
立即学习“Java免费学习笔记(深入)”;
- 写法:new BigDecimal(longValue).doubleValue()
- 注意:这不能恢复丢失精度**,只是让转换过程更可控;doubleValue()仍会截断,但至少跳过了隐式转换的不可见风险
- 关键点:构造BigDecimal必须用String或BigInteger,绝不用double字面量——new BigDecimal(9007199254740993.0)已失真
- 示例:
double d = new BigDecimal("9007199254740993").doubleValue();
验证是否真丢了精度
别靠打印看——System.out.println(d)会自动四舍五入显示。用以下方式实锤:
- 反向转回:(long)d == originalLong?不等就说明丢了
- 查二进制:Double.doubleToLongBits(d) 和 Long.toBinaryString(originalLong),对比有效位
- 简单工具方法:
static boolean isPrecise(long l) { return (long)((double)l) == l; }


















