V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
dramakevinzz
V2EX  ›  问与答

Java BigDecimal 的四舍五入使用问题

  •  
  •   dramakevinzz · 2022-08-31 21:53:00 +08:00 · 1057 次点击
    这是一个创建于 575 天前的主题,其中的信息可能已经有所发展或是发生改变。

    又来论坛求助 V 友了,今天在使用 BigDecimal 四舍五入保留一位小数的时候遇到了很神奇的问题。

    double num1 = 5.95;
    double num2 = 6.95;
    double num3 = 7.95;
    double num4 = 8.95;
    double num5 = 9.95;
    double num6 = 5.43;
    System.out.println(new BigDecimal(num1).setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue()); // 6.0
    System.out.println(new BigDecimal(num2).setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue()); // 7.0
    System.out.println(new BigDecimal(num3).setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue()); // 8.0
    System.out.println(new BigDecimal(num4).setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue()); // 8.9
    System.out.println(new BigDecimal(num5).setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue()); // 9.9
    System.out.println(new BigDecimal(num6).setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue()); // 5.4
    

    8.95 和 9.95 四舍五入应该是 9.0 和 10.0 ,但是输出不是这样,但是 5.95 、6.95 、7.95 又不是这样,这是为啥捏

    11 条回复    2022-09-02 11:51:06 +08:00
    mango88
        1
    mango88  
       2022-08-31 22:09:44 +08:00
    System.out.println(new BigDecimal(num1));
    System.out.println(new BigDecimal(num4));
    这俩你输出看一下就明白了,浮点数的精度问题

    另外构建 BigDecimal 对象推荐用字符串构造
    new BigDecimal("5.95")
    new BigDecimal("8.95")
    这样
    dqzcwxb
        2
    dqzcwxb  
       2022-08-31 22:13:32 +08:00
    mango88
        3
    mango88  
       2022-08-31 22:14:27 +08:00
    或者 BigDecimal.valueOf(double)
    dqzcwxb
        4
    dqzcwxb  
       2022-08-31 22:15:20 +08:00
    dramakevinzz
        5
    dramakevinzz  
    OP
       2022-08-31 22:22:34 +08:00
    @mango88 感谢!这种方法真的就解决了,但是还想请教一下 [浮点数的精度问题] 这个是指什么?可以再解释一下嘛?或者可以再细说一下方向,我查一下,谢谢
    dramakevinzz
        6
    dramakevinzz  
    OP
       2022-08-31 22:24:22 +08:00
    @dqzcwxb 感谢,这张图确实看着就比较明显了,我记得好像是浮点数的存储和表象并不一致,导致有可能类型 X.9+Y.1 最后并不是 Z.0 这种情况,看 CSAPP 的时候记得这里好像是和 IEEE 设计有关,我再翻一下书,查查,感谢
    mineralsalt
        7
    mineralsalt  
       2022-08-31 23:08:39 +08:00   ❤️ 1
    因为浮点的问题, 我现在设计金额相关字段的时候, 全部用 int
    dramakevinzz
        8
    dramakevinzz  
    OP
       2022-08-31 23:25:03 +08:00
    @mineralsalt 金额用 int 吗?这个和日常使用场景怎么契合呢?比如小数,分小数和整数分开存储吗?
    wu67
        9
    wu67  
       2022-09-01 00:17:04 +08:00   ❤️ 1
    @dramakevinzz 用分为单位, 就不存在小数了
    VeryZero
        10
    VeryZero  
       2022-09-01 08:47:25 +08:00
    BigDecimal 源码注释里有解释,建议使用字符串构造
    mineralsalt
        11
    mineralsalt  
       2022-09-02 11:51:06 +08:00
    @dramakevinzz #8 所有金额都用分进行数据库存储, 前端展示的时候格式化一下就行了, 只要存到数据库, 就是分为单位
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1159 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 23:02 · PVG 07:02 · LAX 16:02 · JFK 19:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.