当前位置:首页 > Java技术 > Java 之 double 与 BigDecimal

Java 之 double 与 BigDecimal

2022年08月06日 10:40:53Java技术2

一、常规 double/Double 比较

注意:

1、测试一

double a = 0.1;
double b = 0.1;
System.out.println(a); //0.1
System.out.println(b); //0.1
System.out.println(a > b); //false
System.out.println(a == b); //true
System.out.println("----------");

Double c = 0.1; 
Double d = 0.1; 
System.out.println(c); //0.1
System.out.println(d); //0.1
System.out.println(c == d); //false***
System.out.println(c.compareTo(d)); //0***
System.out.println(Double.compare(c, d)); //0***

2、测试二

double a = 2 * 1.0 / 3;
double b = 0.6666666666666666;
System.out.println(a); //0.6666666666666666
System.out.println(b); //0.6666666666666666
System.out.println(a > b); //false
System.out.println(a == b); //true
System.out.println("----------");

Double c = 2 * 1.0 / 3;
Double d = 0.6666666666666666;
System.out.println(c); //0.6666666666666666
System.out.println(d); //0.6666666666666666
System.out.println(c == d); //false***
System.out.println(c.compareTo(d)); //0***
System.out.println(Double.compare(c, d));//0***

3、测试三

int e = 1;
Double f = 1.0;
System.out.println(f.compareTo(Double.valueOf(e))); //0

4、保留小数点位数的方式

(1) 返回 double 型

  • Math.round 方式:能四舍五入
    public static double decimalDigit(double d, int digit) {
           
        double pow = Math.pow(10, digit);
        return Math.round(d * pow) / pow;
    }
    
  • BigDecimal 方式:
    double d = 114.145;
    BigDecimal b = new BigDecimal(d);
    d = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    System.out.println(d);
    
    • BigDecimal.ROUND_HALF_UP 表示四舍五入
    • BigDecimal.ROUND_HALF_DOWN 表示五舍六入
    • BigDecimal.ROUND_UP表示进位处理(就是直接加1)
    • BigDecimal.ROUND_DOWN表示直接去掉尾数

(2) 返回 String 型

  • #.00:表示保留后两位,直接截掉不要的尾数,不四舍五入
    double d = 114.145;
    DecimalFormat df = new DecimalFormat("#.00");
    String str = df.format(d);
    System.out.println(str);
    
  • %.2f:表示保留后两位,能四舍五入
    double d = 114.145;
    String.format("%.2f", d);
    
  • NumberFormat 方式:
    double d = 114.145
    NumberFormat nf = NumberFormat.getNumberInstance();
    // 保留两位小数
    nf.setMaximumFractionDigits(2);
    // 如果不需要四舍五入,可以使用RoundingMode.DOWN
    nf.setRoundingMode(RoundingMode.UP);
    System.out.println(nf.format(d));
    
    • RoundingMode.HALF_DOWN 表示五舍六入,负数先取绝对值再五舍六入再负数
    • RoundingMode.HALF_UP 表示四舍五入,负数先取绝对值再五舍六入再负数

二、BigDecimal 构造函数

BigDecimal 用来对超过16位有效位的数进行精确的运算

1、常用构造函数

  • BigDecimal(int):创建一个具有参数所指定整数值的对象
  • BigDecimal(double):创建一个具有参数所指定双精度值的对象
  • BigDecimal(long):创建一个具有参数所指定长整数值的对象
  • BigDecimal(String):创建一个具有参数所指定以字符串表示的数值的对象

2、使用注意

(1) 案例

BigDecimal a = new BigDecimal(0.1);
System.out.println("a values is:" + a);
System.out.println("=====================");
BigDecimal b = new BigDecimal("0.1");
System.out.println("b values is:" + b);

//结果
a values is:0.1000000000000000055511151231257827021181583404541015625
=====================
b values is:0.1

(2) 分析

  1. 参数类型为 double 的构造方法的结果有一定的不可预知性,这是因为 0.1 无法准确地表示为 double
  2. 参数类型为 String 的构造方法可预知,即 newBigDecimal(“0.1”) 创建的 BigDecimal 结果为 0.1

    因此,建议优先使用 String 构造方法

  3. 当 double 必须用作 BigDecimal 源时,建议先使用 Double.toString(double) ,然后使用 BigDecimal(String) 构造方法,将double转换为String

    要获取该结果,使用 static valueOf(double) 方法

三、BigDecimal 常用方法

  • add(BigDecimal):BigDecimal 对象中的值相加,返回 BigDecimal 对象
  • subtract(BigDecimal):BigDecimal 对象中的值相减,返回 BigDecimal 对象
  • multiply(BigDecimal):BigDecimal 对象中的值相乘,返回 BigDecimal 对象
  • divide(BigDecimal):BigDecimal 对象中的值相除,返回 BigDecimal 对象
  • toString():将 BigDecimal 对象中的值转换成字符串
  • doubleValue():将 BigDecimal 对象中的值转换成双精度数
  • floatValue():将 BigDecimal 对象中的值转换成单精度数
  • longValue():将 BigDecimal 对象中的值转换成长整数
  • intValue():将 BigDecimal 对象中的值转换成整数

  • abs():绝对值
  • negate():相反数
  • pow(int):幂次运算
  • max(BigDecimal):比较大小并返回大的
  • min(BigDecimal):比较大小并返回小的

四、BigDecimal 方法使用注意

1、比较大小

  • BigDecimal 比较大小一般用 BigDecimal 的 compareTo 方法
int a = num1.compareTo(num2)

返回结果:

  • a = -1:表示 num1 小于 num2
  • a = 0:表示 num1 等于 num2
  • a = 1:表示 num1 大于 num2

2、除法异常

  • divide 方法需设置精确的小数点,如:divide(xxxxx,2)
  • 原因:当 divide 方法不能整除,出现无限循环小数时,会抛异常:java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

五、舍入方式

  • scale():返回小数点后的位数
  • percision():返回数的位数
BigDecimal b1 = new BigDecimal("11.111");
//位数
System.out.println(b1.precision());//5
//小数点后有多少位
System.out.println(b1.scale());//3

  • BigDecimal.ROUND_HALF_UP:四舍五入模式
    BigDecimal b1 = new BigDecimal("1.1449");
    System.out.println(b1.setScale(2, BigDecimal.ROUND_HALF_UP));//1.14
    System.out.println(b1.setScale(3, BigDecimal.ROUND_HALF_UP));//1.145
    
  • BigDecimal.ROUND_HALF_DOWN:五舍六入模式
    BigDecimal b1 = new BigDecimal("1.145");
    System.out.println(b1.setScale(1, BigDecimal.ROUND_HALF_DOWN));//1.1
    //.5 不大于.5 所以会舍去
    System.out.println(b1.setScale(2, BigDecimal.ROUND_HALF_DOWN));//1.14
    
  • BigDecimal.ROUND_HALF_EVEN:银行家舍入法
    • 如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同
    • 如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同
    BigDecimal b1 = new BigDecimal("1.24");
    System.out.println(b1.setScale(1, BigDecimal.ROUND_HALF_EVEN));//1.2
    b1 = new BigDecimal("1.25");
    System.out.println(b1.setScale(1, BigDecimal.ROUND_HALF_EVEN));//1.2
    b1 = new BigDecimal("1.26");
    System.out.println(b1.setScale(1, BigDecimal.ROUND_HALF_EVEN));//1.3
    
  • BigDecimal.ROUND_UP:始终在保留的最后一位加 1
    BigDecimal b1 = new BigDecimal("1.1203");
    System.out.println(b1.setScale(2, BigDecimal.ROUND_UP));//1.13
    System.out.println(b1.setScale(3, BigDecimal.ROUND_UP));//1.121
    
  • BigDecimal.ROUND_DOWN:从舍弃位置直接截断
    BigDecimal b1 = new BigDecimal("1.1209");
    System.out.println(b1.setScale(2, BigDecimal.ROUND_DOWN));//1.12
    System.out.println(b1.setScale(3, BigDecimal.ROUND_DOWN));//1.120
    
  • BigDecimal.ROUND_CEILING:接近正无穷大的舍入模式
    • 如果 BigDecimal 为正,则舍入行为与 ROUND_UP 相同
    • 如果为负,则舍入行为与 ROUND_DOWN 相同
    BigDecimal b1 = new BigDecimal("1.1209");
    System.out.println(b1.setScale(2, BigDecimal.ROUND_CEILING));//1.13
    System.out.println(b1.setScale(3, BigDecimal.ROUND_CEILING));//1.121
    
    BigDecimal b2 = b1.negate();//b1的相反数
    System.out.println(b2.setScale(2, BigDecimal.ROUND_CEILING));//-1.12
    System.out.println(b2.setScale(3, BigDecimal.ROUND_CEILING));//-1.120
    
  • BigDecimal.ROUND_FLOOR:接近负无穷大的舍入模式
    • 如果 BigDecimal 为正,则舍入行为与 ROUND_DOWN 相同
    • 如果为负,则舍入行为与 ROUND_UP 相同
    BigDecimal b1 = new BigDecimal("1.1209");
    System.out.println(b1.setScale(2, BigDecimal.ROUND_FLOOR));//1.12
    System.out.println(b1.setScale(3, BigDecimal.ROUND_FLOOR));//1.120
    
    BigDecimal b2 = b1.negate();
    System.out.println(b2.setScale(2, BigDecimal.ROUND_FLOOR));//-1.13
    System.out.println(b2.setScale(3, BigDecimal.ROUND_FLOOR));//-1.121
    
  • BigDecimal.ROUND_UNNECESSARY:断言请求的操作具有精确的结果,因此不需要舍入

    如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException

    BigDecimal b1 = new BigDecimal("1.25");
    System.out.println(b1.setScale(2, BigDecimal.ROUND_UNNECESSARY));//1.25
    System.out.println(b1.setScale(1, BigDecimal.ROUND_UNNECESSARY));//throw ArithmeticException
    

六、BigDecimal 格式化

1、NumberFormat

NumberFormat 是所有数值格式的抽象基类

NumberFormat 可用于格式化和解析任何语言环境的数值:使代码能够完全独立于小数点、千位分隔符甚至所用特定小数位数的语言环境约定,并与数值格式是否为偶小数无关

(1) 数值格式化

  • getInstance()、getNumberInstance():返回当前默认语言环境的通用数值格式
  • getInstance(Locale)、getNumberInstance(Locale):返回指定语言环境的通用数值格式
  • NumberFormat.setMinimumIntegerDigits(int):设置数的整数部分所允许的最小位数
  • NumberFormat.setMaximumIntegerDigits(int):设置数的整数部分所允许的最大位数
  • NumberFormat.setMinimumFractionDigits(int):设置最少小数点位数,不足以0补位,超出按实际位数输出
  • NumberFormat.setMaximumFractionDigits(int):设置最多保留小数位数,不足不补0
double doubleNum = 12345.676688000;
NumberFormat numberFormat = NumberFormat.getNumberInstance();
System.out.println(numberFormat.format(doubleNum));//12,345.677 默认只保留到小数点后三位
        
numberFormat.setMinimumIntegerDigits(2);
System.out.println(numberFormat.format(doubleNum));//12,345.677 整数部分大于2位按默认最大小数位数3位输出
        
doubleNum = 1234.0;
numberFormat.setMaximumIntegerDigits(3);
System.out.println(numberFormat.format(doubleNum));//234
        
numberFormat = NumberFormat.getInstance();
doubleNum = 12345.6766;
numberFormat.setMinimumFractionDigits(1);
System.out.println(numberFormat.format(doubleNum));//12,345.677 小数部分大于1位,按默认最大小数位数3位输出
        
numberFormat.setMinimumFractionDigits(5);
System.out.println(numberFormat.format(doubleNum));//12,345.67660 不够位数补0
        
numberFormat.setMaximumFractionDigits(1);
System.out.println(numberFormat.format(doubleNum));//12,345.7
        
numberFormat = NumberFormat.getNumberInstance(Locale.US);
doubleNum = 12345.6789;
System.out.println(numberFormat.format(doubleNum));//12,345.679
        
numberFormat = NumberFormat.getNumberInstance(Locale.FRANCE);
System.out.println(numberFormat.format(doubleNum));//12 345,679

(2) 货币格式化

  • getCurrencyInstance():建立一个 NumberFormat 类的对象并返回引用,该引用指定货币格式为系统预设的货币格式
  • getCurrencyInstance(Locale):建立一个 NumberFormat 类的对象并返回引用,该引用的货币格式由 Locale 指定
//按系统预设的货币格式输出,这里是人民币
NumberFormat numberFormat = NumberFormat.getCurrencyInstance();
System.out.println(numberFormat.format(123.456));//¥123.46
        
//按指定的货币格式输出,这里是美元
numberFormat = NumberFormat.getCurrencyInstance(Locale.US);
System.out.println(numberFormat.format(123.456));//$123.46

(3) 百分比格式化

  • getPercentInstance():创建一个 NumberFormat 类的对象并返回其引用,百分比格式为系统预设格式
  • getPercentInstance(Locale):创建一个 NumberFormat 类的对象并返回引用,百分比格式由 Locale 指定
//按系统预设百分比格式输出
double doubleNum = 123.456;
NumberFormat numberFormat = NumberFormat.getPercentInstance();
System.out.println(numberFormat.format(doubleNum));//12,346%

//按指定百分比格式输出,这里是法国格式
numberFormat = NumberFormat.getPercentInstance(Locale.FRANCE);
System.out.println(numberFormat.format(doubleNum));//12 346 %

(4) 工具类

import java.text.DecimalFormat;
import java.text.NumberFormat;

public class NumberDealUtil {
     
    /**
     * 移除数字前面和后面冗余的0,只保留3位小数
     *
     * @param isFormat 是否需要千位分隔符(,)这种格式输出
     * @param num
     * @return
     */
    public static String trim0(boolean isFormat, double num) {
     
        NumberFormat nf = NumberFormat.getInstance();
        if (!isFormat) {
     
            //设置输出格式是否使用“,”分组,默认是使用的
            nf.setGroupingUsed(false);
        }
        String result = nf.format(num);
//        return isFormat ? result : result.replace(",", ""); //用上面代码替换去除分隔符操作
        return result;
    }

    /**
     * 移除数字前面和后面冗余的0
     *
     * @param isFormat      是否需要千位分隔符(,)这种格式输出
     * @param num
     * @param fractionDigit 要保留的小数位数
     * @return
     */
    public static String trim0(boolean isFormat, double num, int fractionDigit) {
     
        NumberFormat nf = NumberFormat.getInstance();
        nf.setMaximumFractionDigits(fractionDigit);
        //setMaximumFractionDigits不会保留小数点和后面多余的0,不需下面正则去除
//        if (result.contains(".") && result.endsWith("0")) {
     
//            result = result.replaceAll("0+?$", "");//去掉多余的0
//            result = result.replaceAll("[.]$", "");//如最后一位是.则去掉
//        }
        if (!isFormat) {
     
            //设置输出格式是否使用“,”分组,默认是使用的
            nf.setGroupingUsed(false);
        }
        String result = nf.format(num);
//        return isFormat ? result : result.replace(",", "");
        return result;
    }

    /**
     * 指定位数输出,不足补0
     * 整数部分如果位数大于需要的位数按实际位数输出
     * 小数部分如果大于需要的位数四舍五入
     *
     * @param num
     * @param integerDigit  整数部分位数
     * @param fractionDigit 小数部分位数
     * @return
     */
    public static String add0Format(double num, int integerDigit, int fractionDigit) {
     
        StringBuilder rule = new StringBuilder();
        if (integerDigit <= 0) {
     
            rule.append("#");
        } else {
     
            for (int i = 0; i < integerDigit; i++) {
     
                rule.append("0");
            }
        }
        if (fractionDigit > 0) {
     
            rule.append(".");
            for (int i = 0; i < fractionDigit; i++) {
     
                rule.append("0");
            }
        }
        DecimalFormat df = new DecimalFormat(rule.toString());
        return df.format(num);
    }

    /**
     * 保留几位小数,不足不补0,小数部分冗余的0也不显示
     *
     * @param num
     * @param fractionDigit 要保留小数的位数
     * @return
     */
    public static String fractionDigitFormat(double num, int fractionDigit) {
     
        /*方法一*/
//        StringBuilder rule = new StringBuilder("#");
//        if (fractionDigit > 0) {
     
//            rule.append(".");
//            for (int i = 0; i < fractionDigit; i++) {
     
//                rule.append("#");
//            }
//        }
//        DecimalFormat df = new DecimalFormat(rule.toString());
//        return df.format(num);

        /*方法二*/
        NumberFormat nf = NumberFormat.getInstance();
        nf.setMaximumFractionDigits(fractionDigit);
        //设置输出格式是否使用“,”分组,这里不使用
        nf.setGroupingUsed(false);
        return nf.format(num);
    }
}

2、DecimalFormat

(1) 符号含义

符号 位置 本地化 含义
0 数字 阿拉伯数字
# 数字 阿拉伯数字若不存在就显示为空
. 数字 小数分隔符或货币小数分隔符
- 数字 减号
, 数字 分组分隔符
E 数字 分割科学计数法中的尾数和指数(在前缀和后缀中无需添加引号)
; 子模式边界 分隔正数和负数子模式
% 前缀或后缀 乘以 100 并显示为百分数
/u2030 前缀或后缀 乘以 1000 并显示为千分数
¤ (\u00A4) 前缀或后缀 货币记号,由货币符号替换:
1. 如果两个同时出现,则用国际货币符号替换
2. 如果出现在某个模式中,则使用货币小数分隔符,而不使用小数分隔符
' 前缀或后缀 用于在前缀或后缀中为特殊字符加引号,例如 “’#’#” 将 123 格式化为 “#123"
ps:要创建单引号本身,请连续使用两个单引号:”# o’'clock"

(2) 0和#配合使用

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%

pi = 12.34567;
//取一位整数
System.out.println(new DecimalFormat("0").format(pi)); //12
//取一位整数和两位小数
System.out.println(new DecimalFormat("0.00").format(pi)); //12.35
//取两位整数和三位小数,整数不足部分以0填补。
System.out.println(new DecimalFormat("00.000").format(pi)); //12.346
//取所有整数部分
System.out.println(new DecimalFormat("#").format(pi)); //12
//以百分比方式计数,并取两位小数
System.out.println(new DecimalFormat("#.##%").format(pi)); //1234.57%

pi = 12.34;
//整数
System.out.println(new DecimalFormat("6").format(pi)); //612
System.out.println(new DecimalFormat("60").format(pi)); //612
System.out.println(new DecimalFormat("06").format(pi)); //126
System.out.println(new DecimalFormat("00600").format(pi)); //00126
System.out.println(new DecimalFormat("#####60000").format(pi)); //00126
//小数
System.out.println(new DecimalFormat(".6").format(pi)); //12.6
System.out.println(new DecimalFormat(".06").format(pi)); //12.36
System.out.println(new DecimalFormat(".60").format(pi)); //12.36
System.out.println(new DecimalFormat(".0600").format(pi)); //12.3406
System.out.println(new DecimalFormat(".6000").format(pi)); //12.3406
System.out.println(new DecimalFormat(".600000##").format(pi)); //12.340006

注意

  1. 整数:0 和 # 配合使用,只能是 ##00,即 # 在前,0 在后
    1. 若是 n 个 0,就从个位开始向高位填充,如果有值就是原来的值,没有就填充0
    2. 若都是 #,没有实际意义,不管是几个 #,最后的结果都是原来的整数
  2. 小数:0 和 # 配合使用,只能是 .00##,即 0 在前,# 在后
    1. 若 n 个 0,就是保留 n 位小数,小数不足的部分用 0 填充
    2. 若 n 个 #,就是保留 n 位小数,小数不足部分没有就是没有
  3. 数字 1-9
    1. 整数

      • 若没有 0 或 #,默认在后面拼接整数
      • 若有 0 或 #,找到第一个 0 或 # 的位置,然后找出所有的0或#拼在一起

        在第一个 0 或 # 出现的位置插入响应的格式化以后的值

    2. 小数

      • 若没有 0 或 #,格式化是什么就显示什么
      • 若有 0 或 #,找出所有的 0 或 # 拼在一起

        在小数点的后面插入响应的格式化以后的值

(3) 科学计数法 E

double pi = 123456789.3456;
System.out.println(new DecimalFormat("0E0").format(pi)); //1E8
System.out.println(new DecimalFormat("0E00").format(pi)); //1E08
System.out.println(new DecimalFormat("#E0").format(pi)); //.1E9
System.out.println(new DecimalFormat("##E0").format(pi)); //1.2E8
System.out.println(new DecimalFormat("###E0").format(pi)); //123E6
System.out.println(new DecimalFormat("####E0").format(pi)); //1.235E8
System.out.println(new DecimalFormat("#####E0").format(pi)); //1234.6E5
System.out.println(new DecimalFormat("######E0").format(pi)); //123.457E6
System.out.println(new DecimalFormat("#######E0").format(pi)); //12.34568E7
System.out.println(new DecimalFormat("########E0").format(pi)); //1.2345679E8
System.out.println(new DecimalFormat("#########E0").format(pi)); //123456789E0
System.out.println(new DecimalFormat("##########E0").format(pi)); //123456789.3E0

pi = 12345678.3456;
System.out.println(new DecimalFormat("0E0").format(pi)); //1E7
System.out.println(new DecimalFormat("0E00").format(pi)); //1E07
System.out.println(new DecimalFormat("#E0").format(pi)); //.1E8
System.out.println(new DecimalFormat("##E0").format(pi)); //12E6
System.out.println(new DecimalFormat("###E0").format(pi)); //12.3E6
System.out.println(new DecimalFormat("####E0").format(pi)); //1235E4
System.out.println(new DecimalFormat("#####E0").format(pi)); //123.46E5
System.out.println(new DecimalFormat("######E0").format(pi)); //12.3457E6
System.out.println(new DecimalFormat("#######E0").format(pi)); //12.34568E7
System.out.println(new DecimalFormat("########E0").format(pi)); //12345678E0
System.out.println(new DecimalFormat("#########E0").format(pi)); //12345678.3E0
System.out.println(new DecimalFormat("##########E0").format(pi)); //12345678.35E0

//0 的个数决定最后输出结果的位数,与 0 的位置无关
pi = 12345;
System.out.println(new DecimalFormat("###.##E0").format(pi)); //12.345E3
System.out.println(new DecimalFormat("##0.##E0").format(pi)); //12.345E3
System.out.println(new DecimalFormat("##0.0##E0").format(pi)); //12.345E3
System.out.println(new DecimalFormat("##0.00000##E0").format(pi)); //12.3450E3
System.out.println(new DecimalFormat("#00.0000##E0").format(pi)); //12.3450E3
System.out.println(new DecimalFormat("#00.00000##E0").format(pi)); //12.34500E3

总结

  1. 使用科学计数法,首先保证 E 前面有 0 或 #,否则就不是科学计数法
  2. E 后面必须是 0,0 的个数对后面的显示有影响,多余就会填充 0
  3. E 前面只有一个 #,得到的结果肯定是 . 开头的结果
  4. E 前面 # 与 0 的总个数决定后面的指数

    具体:总个数和指数比较:

    • 若指数的值大于总个数,则得到的指数的值是个数的倍数
    • 若指数的值小于等于总个数,则得到的指数的值等于总个数
  5. 整个模式中的 0 的总个数决定最后输出结果的位数,并且与 0 的位置无关
  6. 如果整数部分需要保留几位数,就使用几个 0

(4) 分组分隔符

double pi = 1299792458;
//每三位以逗号进行分隔
System.out.println(new DecimalFormat(",###").format(pi)); //1,299,792,458
System.out.println(new DecimalFormat(",##").format(pi)); //12,99,79,24,58
System.out.println(new DecimalFormat("###,##").format(pi)); //12,99,79,24,58

(5) 减号

double pi = 3.14;
System.out.println(new DecimalFormat("-0.00").format(pi)); //-3.14

(6) % 将数字乘以100

double pi = 0.1234;
System.out.println(new DecimalFormat("0.00%").format(pi)); //12.34%
System.out.println(new DecimalFormat("0%.00").format(pi)); //12.34%
System.out.println(new DecimalFormat("%0.00").format(pi)); //%12.34

(7) \u2030 将数字乘以1000

double pi = 0.1234;
System.out.println(new DecimalFormat("0.00\u2030").format(pi)); //123.40‰
System.out.println(new DecimalFormat("0.0\u20300").format(pi)); //123.40‰
System.out.println(new DecimalFormat("\u20300.00").format(pi)); //‰123.40

(8) ¤(\u00A4) 本地化货币符号

double pi = 1234.5678;
System.out.println(new DecimalFormat(",000.00¤").format(pi)); //1,234.57¥
System.out.println(new DecimalFormat(",000.¤00").format(pi)); //1,234.57¥
System.out.println(new DecimalFormat("¤,000.00").format(pi)); //¥1,234.57
System.out.println(new DecimalFormat(",00¤0.¤00").format(pi)); //1,234.57¥¥
System.out.println(new DecimalFormat("¤,000.¤00").format(pi)); //¥1,234.57¥
System.out.println(new DecimalFormat(",000.00¤¤").format(pi)); //1,234.57CNY

(9) ' 用于引用特殊的字符,作为前缀或后缀

double pi = 4.5678;
System.out.println(new DecimalFormat("'#'0.00").format(pi)); //#4.57
System.out.println(new DecimalFormat("'^ _ ^'0.00").format(pi)); //^ _ ^4.57
//使用'本身作为前缀或后缀
System.out.println(new DecimalFormat("''0.00").format(pi)); //'4.57

七、工具类

package org.example;

import java.math.BigDecimal;

/**
 * 用于高精确处理常用的数学运算
 */
public class ArithmeticUtils {
     
    //默认除法运算精度
    private static final int DEF_DIV_SCALE = 10;

    /**
     * 提供精确的加法运算
     *
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */
    public static double add(double v1, double v2) {
     
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }

    /**
     * 提供精确的加法运算
     *
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */
    public static BigDecimal add(String v1, String v2) {
     
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.add(b2);
    }

    /**
     * 提供精确的加法运算
     *
     * @param v1    被加数
     * @param v2    加数
     * @param scale 保留scale 位小数
     * @return 两个参数的和
     */
    public static String add(String v1, String v2, int scale) {
     
        if (scale < 0) {
     
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * 提供精确的减法运算
     *
     * @param v1 被减数
     * @param v2 减数
     * @return 两个参数的差
     */
    public static double sub(double v1, double v2) {
     
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }

    /**
     * 提供精确的减法运算。
     *
     * @param v1 被减数
     * @param v2 减数
     * @return 两个参数的差
     */
    public static BigDecimal sub(String v1, String v2) {
     
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.subtract(b2);
    }

    /**
     * 提供精确的减法运算
     *
     * @param v1    被减数
     * @param v2    减数
     * @param scale 保留scale 位小数
     * @return 两个参数的差
     */
    public static String sub(String v1, String v2, int scale) {
     
        if (scale < 0) {
     
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * 提供精确的乘法运算
     *
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */
    public static double mul(double v1, double v2) {
     
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }

    /**
     * 提供精确的乘法运算
     *
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */
    public static BigDecimal mul(String v1, String v2) {
     
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.multiply(b2);
    }

    /**
     * 提供精确的乘法运算
     *
     * @param v1    被乘数
     * @param v2    乘数
     * @param scale 保留scale 位小数
     * @return 两个参数的积
     */
    public static double mul(double v1, double v2, int scale) {
     
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return round(b1.multiply(b2).doubleValue(), scale);
    }

    /**
     * 提供精确的乘法运算
     *
     * @param v1    被乘数
     * @param v2    乘数
     * @param scale 保留scale 位小数
     * @return 两个参数的积
     */
    public static String mul(String v1, String v2, int scale) {
     
        if (scale < 0) {
     
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
     * 小数点以后10位,以后的数字四舍五入
     *
     * @param v1 被除数
     * @param v2 除数
     * @return 两个参数的商
     */
    public static double div(double v1, double v2) {
     
        return div(v1, v2, DEF_DIV_SCALE);
    }

    /**
     * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
     * 定精度,以后的数字四舍五入
     *
     * @param v1    被除数
     * @param v2    除数
     * @param scale 表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static double div(double v1, double v2, int scale) {
     
        if (scale < 0) {
     
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
     * 定精度,以后的数字四舍五入
     *
     * @param v1    被除数
     * @param v2    除数
     * @param scale 表示需要精确到小数点以后几位
     * @return 两个参数的商
     */
    public static String div(String v1, String v2, int scale) {
     
        if (scale < 0) {
     
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v1);
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * 提供精确的小数位四舍五入处理
     *
     * @param v     需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double round(double v, int scale) {
     
        if (scale < 0) {
     
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 提供精确的小数位四舍五入处理
     *
     * @param v     需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static String round(String v, int scale) {
     
        if (scale < 0) {
     
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(v);
        return b.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * 取余数
     *
     * @param v1    被除数
     * @param v2    除数
     * @param scale 小数点后保留几位
     * @return 余数
     */
    public static String remainder(String v1, String v2, int scale) {
     
        if (scale < 0) {
     
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * 取余数  BigDecimal
     *
     * @param v1    被除数
     * @param v2    除数
     * @param scale 小数点后保留几位
     * @return 余数
     */
    public static BigDecimal remainder(BigDecimal v1, BigDecimal v2, int scale) {
     
        if (scale < 0) {
     
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        return v1.remainder(v2).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 比较大小
     *
     * @param v1 被比较数
     * @param v2 比较数
     * @return 如果v1 大于v2 则 返回true 否则false
     */
    public static boolean compare(String v1, String v2) {
     
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        int bj = b1.compareTo(b2);
        boolean res;
        if (bj > 0)
            res = true;
        else
            res = false;
        return res;
    }
}

作者:yin__ren
来源链接:https://blog.csdn.net/yin__ren/article/details/108194471

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/java/18181.html

标签: BigDecimal
分享给朋友:

“Java 之 double 与 BigDecimal” 的相关文章

java.math.BigDecimal常用方法

+构造函数 BigDecimal(BigInteger val) 将BigInteger转化为BigDecimal。 BigDecimal(BigInteger unscaledVal, int scale) 将B...

Java 使用BigDecimal进行高精度加减乘除

有时候我们计算金钱或者其他一些计算的时候需要高精度的计算加减乘除,可以使用BigDecimal 加: BigDecimal num1 = new BigDecimal("100.569"); BigDecimal num2 = new Big...

[转]BigDecimal使用(整理)

原文地址:https://www.jianshu.com/p/2947868d76eb 应用场景 大多数的商业计算中,一般采用java.math.BigDecimal类来进行精确计算。比如:货币 使用 1、构建BigDecima...

Java:利用BigDecimal类巧妙处理Double类型精度丢失

Java:利用BigDecimal类巧妙处理Double类型精度丢失

文章目录 本篇要点 经典问题:浮点数精度丢失 十进制整数如何转化为二进制整数? 十进制小数如何转化为二进制数?...

BigDecimal 与 doubleValue 的使用 ,以及四舍五入

/** * 保存发票信息 * @param controller * @return * @throws ParseException * @throws ActiveRecordException */ @...

BigDecimal转为int类型

BigDecimal转为int类型

直接调用BigDecimal的intValue()方法 示例: BigDecimal a = new BigDecimal(“1.1”); int b = a.intValue(); BigDecimal运算方法:...

JDK中BigDecimal的代码实现

package java.math; import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.PrintStream;...

BigDecimal 使用compareTo比较大小

1.BigDecimal的比较模式  BigDecimal b1 = new BigDecimal(0.1); BigDecimal b2 = new BigDecimal(0.2); int c = b1.compareTo(b2); // -1 c=1表示...

【java提高】(19)---BigDecimal详解和精度问题

【java提高】(19)---BigDecimal详解和精度问题

BigDecimal详解和精度问题 一、背景 在实际开发中,对于 不需要任何准确计算精度的属性可以直接使用float或double,但是如果需要精确计算结果,则必须使用BigDecimal,例如价格、质量。 为什么这么说,主要有两点...

BigDecimal<转载>

前言 我们都知道浮点型变量在进行计算的时候会出现丢失精度的问题。如下一段代码: System.out.println(0.05 + 0.01); System.out.println(1.0 - 0.42); System.out.printl...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。