You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将18-19位double值转换为long时出现数值偏差问题求助

18-19位整数型double转long精度丢失问题解决

我需要把18-19位、小数部分固定为.0的double类型值转换为long类型,但直接用longValue()方法转换会出现精度丢失,结果和预期不符。

示例输入

double val1 = 1000000000000007403.0;
double val2 = 2223372036854774845.0;

测试代码

public static void main (String args[]){
    
    double val1 = 1000000000000007403.0;   // 输入值
    double val2 = 2223372036854774845.0;   // 输入值

    Double double1 = Double.valueOf(val1);
    Double double2 = Double.valueOf(val2);
    
    long val1Long = double1.longValue();
    long val2Long = double2.longValue();
    System.out.println(val1Long);
    System.out.println(val2Long);   
}

结果对比

输出结果:

1000000000000007424、2223372036854774784

预期结果:

1000000000000007403、2223372036854774845

问题规律:当double值的有效数字超过14-15位时,就会出现这种精度丢失情况。


原因分析

double是64位浮点数,其尾数部分仅52位(加上隐含的1位共53位),对应十进制的有效数字最多只有15-17位。当你把18-19位的整数赋值给double时,double无法精确存储该数值,会自动近似为最接近的可表示值——这就是调试时看到的double值已经偏离原始输入的原因,后续转long自然得不到正确结果。


解决方案

  1. 从源头避免用double存储大整数
    如果能控制输入传递方式,不要用double存储高精度整数,改用字符串或BigDecimal类型接收,可完整保留原始数值,这是最优解:

    // 字符串转long
    String val1Str = "1000000000000007403";
    long val1Long = Long.parseLong(val1Str);
    
    // BigDecimal转long
    BigDecimal bdVal2 = new BigDecimal("2223372036854774845");
    long val2Long = bdVal2.longValueExact();
    
  2. 仅能拿到已有double值时的补救方法
    若无法修改输入类型,可先将double转为字符串,去掉末尾的.0后再转long,但注意:这种方式只能恢复double存储的近似值,无法还原被double丢失的原始精度(因为double本身已存储错误值):

    double val1 = 1000000000000007403.0;
    String val1Str = Double.toString(val1).replace(".0", "");
    long val1Long = Long.parseLong(val1Str);
    

内容的提问来源于stack exchange,提问作者Keshav Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 19:32:42