浅谈使用DecimalFormat保留小数点的问题

  在某些场景下,我们经常要将数字进行格式化,比如取2位小数,或者四舍五入、取整等等,这是最常见的。那么我们应该怎么去实现呢?

在这里插入图片描述

  Java 提供DecimalFormat类,它可以帮你用最快的速度将数字格式化为你需要的样子。详情请看下面案例列举:

double pi = 3.1415927;//圆周率约等
//取一位整数
System.out.println(new DecimalFormat("0").format(pi));//3
//取一位整数和两位小数
System.out.println(new DecimalFormat("0.00").format(pi));//3.14
//取两位整数和三位小数,整数不足部分以0填补。
System.out.println(new DecimalFormat("00.000").format(pi));//03.142
//取所有整数部分
System.out.println(new DecimalFormat("#").format(pi));//3
//以百分比方式计数,并取两位小数
System.out.println(new DecimalFormat("#.##%").format(pi));//314.16%
long c = 299792458;//光速
//显示为科学计数法,并取五位小数
System.out.println(new DecimalFormat("#.#####E0").format(c));//2.99792E8
//显示为两位整数的科学计数法,并取四位小数
System.out.println(new DecimalFormat("00.####E0").format(c));//29.9792E7
//每三位以逗号进行分隔。
System.out.println(new DecimalFormat(",###").format(c));//299,792,458
//将格式嵌入文本
System.out.println(new DecimalFormat("光速大小为每秒,###米。").format(c));//光速大小为每秒299,792,458米。

DecimalFormat 类主要靠 # 和 0 两种占位符号来指定数字长度。

  • 0:表示如果位数不足则以 0 填充,
  • #:表示只要有可能就把数字拉上这个位置(不包括 0)。

上面的例子包含了差不多所有的基本用法,如果你想了解更多,请参考 DecimalFormat 类的文档。

📌个别案例分析:

  针对上面的使用,常用的就是保留小数点问题,对此,程序羊将DecimalFormat 抽取进行三个简单的封装,分别是默认的、正常四舍五入和只保留,不进行四舍五入的三个方法,方便下面案例进行调用演示:

package com.example.business.util;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;

/**
 * @ClassName: DecimalFormatUtil
 * @Description: 保留小数点相关类
 * @Author yang
 * @Date 2022/9/21
 * @Version 1.0
 */
public class DecimalFormatUtil {

    /**
     * 获取Double格式化,根据format保留n个小数点(不会四舍五入)
     * 默认采用的舍入策略是:四舍六入五奇偶。(以保留一位小数为例)
     * 如 4.56 就是 4.6, 最后一位小数大于等于 6 就向前进一位.
     * 4.54 就是 4.5, 最后一位小数小于等于 4, 就舍去
     * 4.45 就是 4.4 ; 4.55 就是 4.6 最后一位小数是 5 的时候,当前一位是奇数的时候就进一位凑成偶数,当前一位是偶数的时候就舍去.
     * 不要四舍五入的方法就是: df.setRoundingMode(RoundingMode.DOWN);
     *
     * @param strVal Double值
     * @param format 格式化字符串,#.##代表获取所有整数位并保留两位小数
     * @return
     */
    public static String getDoubleFormat(Double strVal, String format) {
        if (format == null || format.isEmpty() || format.equals("null")) {
            format = "#.##";
        }
        DecimalFormat df = new DecimalFormat(format);
        df.setRoundingMode(RoundingMode.DOWN);
        String fm = df.format(strVal);
        return fm;
    }

    /**
     * 获取Double格式化,根据format保留n个小数点(会四舍五入)
     *
     * @param strVal Double值
     * @param format 格式化字符串,#.##代表获取所有整数位并保留两位小数
     * @return
     */
    public static String getDoubleFormatByRound(Double strVal, String format) {
        if (format == null || format.isEmpty() || format.equals("null")) {
            format = "#.##";
        }
        DecimalFormat df = new DecimalFormat(format);
        df.setRoundingMode(RoundingMode.HALF_UP);//HALF_UP四舍五入
        String fm = df.format(new BigDecimal(String.valueOf(strVal)));
        return fm;
    }

    /**
     * 获取Double格式化,根据format保留n个小数点(默认策略)
     *
     * @param strVal Double值
     * @param format 格式化字符串,#.##代表获取所有整数位并保留两位小数
     * @return
     */
    public static String getDoubleFormatByDefault(Double strVal, String format) {
        if (format == null || format.isEmpty() || format.equals("null")) {
            format = "#.##";
        }
        DecimalFormat df = new DecimalFormat(format);
        String fm = df.format(new BigDecimal(String.valueOf(strVal)));
        return fm;
    }

}

(1)默认的:比较少用,使用的是进位方式是RoundingMode.HALF_EVEN,此舍入模式也称为“银行家算法”,主要在美国使用。

银行家算法:四舍六入五考虑,五后非零就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一。

规律就是看进舍位的前一位是奇数还是偶数

  • 奇数:四舍五入
  • 偶数:五舍六入
  • 若进舍位是5,且后面非0,进一
  • 如3.25,保存一位小数,进舍位前一位是2,2是偶数,五舍六入的结果就是3.2,如果是3.26,那结果就是3.3;
  • 如3.251,保存一位小数,5后面非0,所以会进一,即3.3;
  • 如3.35,保存一位小数,进舍位前一位是3,3是奇数,四舍五入的结果就是3.4。

(2)如果想实现普通的四舍五入,增加下面代码,切换进位方式 df.setRoundingMode(RoundingMode.HALF_UP);

(3)如果不想实现四舍五入,增加下面代码,切换进位方式,即相当于截断 df.setRoundingMode(RoundingMode.DOWN);

format的时候注意要使用 new BigDecimal,防止浮点型出现精度丢失的问题!

📌各种场景案例演示:

1.使用#占位符号,保留一位小数点,没有0的情况

double num = 4.56;
String doubleFormat1 = DecimalFormatUtil.getDoubleFormatByDefault(num, "#.#");
String doubleFormat2 = DecimalFormatUtil.getDoubleFormatByRound(num, "#.#");
String doubleFormat3 = DecimalFormatUtil.getDoubleFormat(num, "#.#");
System.out.println("DecimalFormat默认策略:" + doubleFormat1);
System.out.println("HALF_UP正常四舍五入:" + doubleFormat2);
System.out.println("只保留,不进行四舍五入" + doubleFormat3);

输出结果:

DecimalFormat默认策略:4.6
HALF_UP正常四舍五入:4.6
只保留,不进行四舍五入:4.5

2.使用#占位符号,保留一位小数点,有0的情况,不保留0

double num = 3.05;
String doubleFormat1 = DecimalFormatUtil.getDoubleFormatByDefault(num, "#.#");
String doubleFormat2 = DecimalFormatUtil.getDoubleFormatByRound(num, "#.#");
String doubleFormat3 = DecimalFormatUtil.getDoubleFormat(num, "#.#");
System.out.println("DecimalFormat默认策略:" + doubleFormat1);
System.out.println("HALF_UP正常四舍五入:" + doubleFormat2);
System.out.println("只保留,不进行四舍五入:" + doubleFormat3);

输出结果:

DecimalFormat默认策略:3
HALF_UP正常四舍五入:3.1
只保留,不进行四舍五入:3

PS:使用#占位符号的时候,遇到保留位数刚好有0存在的时候,则会省略,要想保留,使用0占位符号来指定,如下:

3.使用0占位符号,保留一位小数点,有0的情况,保留0

double num = 3.05;
String doubleFormat1 = DecimalFormatUtil.getDoubleFormatByDefault(num, "0.0");
String doubleFormat2 = DecimalFormatUtil.getDoubleFormatByRound(num, "0.0");
String doubleFormat3 = DecimalFormatUtil.getDoubleFormat(num, "0.0");
System.out.println("DecimalFormat默认策略:" + doubleFormat1);
System.out.println("HALF_UP正常四舍五入:" + doubleFormat2);
System.out.println("只保留,不进行四舍五入:" + doubleFormat3);

输出结果:

DecimalFormat默认策略:3.0
HALF_UP正常四舍五入:3.1
只保留,不进行四舍五入:3.0

4.使用0占位符号,保留四位小数点,且目标数的位数不够时

double num = 4.54;
String doubleFormat1 = StringVerifyUtil.getDoubleFormatByDefault(num, "0.0000");
String doubleFormat2 = StringVerifyUtil.getDoubleFormatByRound(num, "0.0000");
String doubleFormat3 = StringVerifyUtil.getDoubleFormat(num, "0.0000");
System.out.println("DecimalFormat默认策略:" + doubleFormat1);
System.out.println("HALF_UP正常四舍五入:" + doubleFormat2);
System.out.println("只保留,不进行四舍五入:" + doubleFormat3);

输出结果:

DecimalFormat默认策略:4.5400
HALF_UP正常四舍五入:4.5400
只保留,不进行四舍五入:4.5400

5.使用#占位符号,保留四位小数点,且目标数的位数不够时

double num = 4.54;
String doubleFormat1 = StringVerifyUtil.getDoubleFormatByDefault(num, "#.####");
String doubleFormat2 = StringVerifyUtil.getDoubleFormatByRound(num, "#.####");
String doubleFormat3 = StringVerifyUtil.getDoubleFormat(num, "#.####");
System.out.println("DecimalFormat默认策略:" + doubleFormat1);
System.out.println("HALF_UP正常四舍五入:" + doubleFormat2);
System.out.println("只保留,不进行四舍五入:" + doubleFormat3);

输出结果:

DecimalFormat默认策略:4.54
HALF_UP正常四舍五入:4.54
只保留,不进行四舍五入:4.54

在这里插入图片描述
创作不易,感谢您的点赞与支持。
  • 21
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序yang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值