第十一章 Java数字处理类(1.2)

一、数字处理类

Java中提供了丰富的类库,帮助开发人员进行数学运算、数字格式化等与数字处理有关的操作。

1.1、java.text.NumberFormat

在JDK提供的java.text包下,有一个NumberFormat类,该类提供了丰富的数字格式化方法,NumberFormat类是一个常用的数字处理类。
其常用的API如下:

方法 返回值 方法说明
getInstance() NumberFormat 返回当前默认区域的通用数字格式实例
getInstance(Locale inLocale) NumberFormat 返回指定区域设置的通用数字格式
getIntegerInstance() NumberFormat 返回当前默认的整数数字格式实例
getAvailableLocales() Locale[] 返回一个所有可用区域的数组
getCurrencyInstance() NumberFormat 返回当前默认区域的货币数字格式实例
getCurrencyInstance(Locale inLocale) NumberFormat 返回指定区域设置的货币数字格式
getPercentInstance() NumberFormat 返回当前默认区域的百分比数字格式实例
getPercentInstance(Locale inLocale) NumberFormat 返回指定区域设置的百分比数字格式
format(long number) String 数字格式化
format(double number) String 数字格式化
下面是一个示例:
import java.text.NumberFormat;
import java.util.Locale;

public class Test11 {
public static void main(String[] args) {
// 声明两个数字变量并初始化
int num1 = 108732965;
double num2 = 6314296.1816;

    // 测试各种形式的数字格式化
    // 通用数字格式
    NumberFormat nf1 = NumberFormat.getInstance();
    System.out.println("nf1.format(num1) = " + nf1.format(num1));
    System.out.println("nf1.format(num2) = " + nf1.format(num2));

    NumberFormat nf2 = NumberFormat.getInstance(Locale.US);
    System.out.println("nf2.format(num1) = " + nf2.format(num1));
    System.out.println("nf2.format(num2) = " + nf2.format(num2));

	// 货币数字格式
    NumberFormat nf3 = NumberFormat.getCurrencyInstance();
    System.out.println("nf3.format(num1) = " + nf3.format(num1));
    System.out.println("nf3.format(num2) = " + nf3.format(num2));

    NumberFormat nf4 = NumberFormat.getCurrencyInstance(Locale.US);
    System.out.println("nf4.format(num1) = " + nf4.format(num1));
    System.out.println("nf4.format(num2) = " + nf4.format(num2));

	// 百分比数字格式
    NumberFormat nf5 = NumberFormat.getPercentInstance();
    System.out.println("nf5.format(num1) = " + nf5.format(num1));
    System.out.println("nf5.format(num2) = " + nf5.format(num2));

    NumberFormat nf6 = NumberFormat.getPercentInstance(Locale.US);
    System.out.println("nf6.format(num1) = " + nf6.format(num1));
    System.out.println("nf6.format(num2) = " + nf6.format(num2));
}

}
执行输出结果:

`nf1.format(num1) = 108,732,965
nf1.format(num2) = 6,314,296.182
nf2.format(num1) = 108,732,965
nf2.format(num2) = 6,314,296.182
nf3.format(num1) = ¥108,732,965.00
nf3.format(num2) = ¥6,314,296.18
nf4.format(num1) = $108,732,965.00
nf4.format(num2) = $6,314,296.18
nf5.format(num1) = 10,873,296,500%
nf5.format(num2) = 631,429,618%
nf6.format(num1) = 10,873,296,500%
nf6.format(num2) = 631,429,618%
解释:
java.text.NumberFormat类是一个抽象类,通过该类的各种getXXXInstance方法获得的数字格式对象事实上都是其派生类的对象。
java.text.NumberFormat类在获得各种数字格式对象时,可以使用java.util.Locale来指定区域,可用的区域在java.util.Locale类中均已经被声明为常量。

1.2、java.text.DecimalFormat

开发人员在使用java.text.NumberFormat类来进行数字格式化时,大多数情况下其实是在使用java.text.DecimalFormat类的对象,开发人员也可以直接使用java.text.DecimalFormat类的对象来实现更加灵活的数字格式化操作。

下面是一个示例:
import java.text.DecimalFormat;

public class Test12 {
public static void main(String[] args) {
// 声明两个数字变量并初始化
int num1 = 108732965;
double num2 = 6314296.1816;

    // 实例化多个DecimalFormat类的实例
    DecimalFormat df1 = new DecimalFormat();
    DecimalFormat df2 = new DecimalFormat("#,####");
    DecimalFormat df3 = new DecimalFormat("#,###.000");
    DecimalFormat df4 = new DecimalFormat("0.##E0");
    DecimalFormat df5 = new DecimalFormat("#,###.00%");

    // 格式化并打印
    System.out.println("df1.format(num1) = " + df1.format(num1));
    System.out.println("df1.format(num2) = " + df1.format(num2));
    System.out.println("df2.format(num1) = " + df2.format(num1));
    System.out.println("df2.format(num2) = " + df2.format(num2));
    System.out.println("df3.format(num1) = " + df3.format(num1));
    System.out.println("df3.format(num2) = " + df3.format(num2));
    System.out.println("df4.format(num1) = " + df4.format(num1));
    System.out.println("df4.format(num2) = " + df4.format(num2));
    System.out.println("df5.format(num1) = " + df5.format(num1));
    System.out.println("df5.format(num2) = " + df5.format(num2));
}

}
执行输出结果:

df1.format(num1) = 108,732,965
df1.format(num2) = 6,314,296.182
df2.format(num1) = 1,0873,2965
df2.format(num2) = 631,4296
df3.format(num1) = 108,732,965.000
df3.format(num2) = 6,314,296.182
df4.format(num1) = 1.09E8
df4.format(num2) = 6.31E6
df5.format(num1) = 10,873,296,500.00%
df5.format(num2) = 631,429,618.16%
解释:
实例化java.text.DecimalFormat类的对象时,可以使用无参构造方法,获得的对象使用默认的格式化样式;也可以使用含参构造方法,指定格式化样式。指定格式化样式时,需要使用格式符,常用的格式符如下:
格式符 作用
#代表一个数字位置,如果该位置没有数字,则不会显示
, 代表数字中的分隔符
0 代表一个数字位置,如果该位置没有数字,则用0来补充,小数中多余部分四舍五入
. 表示小数点
E 科学记数法
% 用百分数表示数字

1.3、java.lang.Math

java.lang包下,JDK提供了Math类。该类中提供了大量和基本数学运算相关的方法和常量,方法如加减乘除、指数、对数、平方根、三角函数等,常量最主要的两个是Math.E和Math.PI,分表示自然对数的底数和圆周率。该类中用于基本数学运算的方法均是静态成员方法,直接用类名调用,使用非常方便。

java.lang.Math类中的常用API如下:

方法 返回值 方法说明
abs(int a) int 返回绝对值
abs(long a) long 返回绝对值
abs(float a) float 返回绝对值
abs(double a) double 返回绝对值
sin(double a) double 求指定double类型参数的正弦值
cos(double a) double 求指定double类型参数的余弦值
tan(double a) double 求指定double类型参数的正切值
asin(double a) double 求指定double类型参数的反正弦值
acos(double a) double 求指定double类型参数的反余弦值
atan(double a) double 求指定double类型参数的反正切值
toRadians(double angdeg) double 将角度转换为弧度
toDegrees(double angrad) double 将参数转化为角度
exp(double a) double 返回自然数底数e的参数次方
log(double a) double 返回参数的自然底数的对数值
log10(double a) double 返回参数的以10为底数的对数值
sqrt(double a) double 求参数的算术平方根
pow(double a, double b) double 返回第一个参数的第二个参数次方
addExact(int x, int y) int 返回其参数的总和,结果溢出则抛出异常
addExact(long x, long y) long 返回其参数的总和,结果溢出则抛出异常
incrementExact(int a) int 返回参数自增1的结果,结果溢出则抛出异常
incrementExact(long a) long 返回参数自增1的结果,结果溢出则抛出异常
subtractExact(int x, int y) int 返回参数的差,结果溢出则抛出异常
subtractExact(long x, long y) long 返回参数的差,结果溢出则抛出异常
decrementExact(int a) int 返回参数自减1的结果,结果溢出则抛出异常
decrementExact(long a) long 返回参数自减1的结果,结果溢出则抛出异常
multiplyExact(int x, int y) int 返回参数的乘积,结果溢出则抛出异常
multiplyExact(long x, long y) long 返回参数的乘积,结果溢出则抛出异常
max(double a, double b) double 返回参数中的较大值
max(float a, float b) float 返回参数中的较大值
max(int a, int b) int 返回参数中的较大值
max(long a, long b) long 返回参数中的较大值
min(double a, double b) double 返回参数中的较小值
min(float a, float b) float 返回参数中的较小值
min(int a, int b) int 返回参数中的较小值
min(long a, long b) long 返回参数中的较小值
random() double 随机返回一个[0.0, 1.0)区间内的double值
ceil(double a) double 返回大于或等于参数的最小 double值,等于一个数学整数
floor(double a) double 返回小于或等于参数的最大 double值,等于一个数学整数
round(float a) int 返回最接近参数的int值
round(double a) long 返回最接近参数的long值
下面是一个示例:

public class Test13 {
public static void main(String[] args) {
// 测试Math类中的常用方法
// 绝对值
System.out.println("Math.abs(-1314) = " + Math.abs(-1314));
// 正弦
System.out.println("Math.sin(Math.toRadians(30)) = " + Math.sin(Math.toRadians(30)));
// 以e为底数,100的对数
System.out.println("Math.log(100) = " + Math.log(100));
// 以10为底数,100的对数
System.out.println("Math.log10(100) = " + Math.log10(100));
// 算数平方根
System.out.println("Math.sqrt(3) = " + Math.sqrt(3));
// 幂
System.out.println("Math.pow(2,4) = " + Math.pow(2, 4));
// 加
System.out.println("Math.addExact(12, 13) = " + Math.addExact(12, 13));
// 减
System.out.println("Math.subtractExact(13, 7) = " + Math.subtractExact(13, 7));
// 乘
System.out.println("Math.multiplyExact(25,8) = " + Math.multiplyExact(25, 8));
// 最大值
System.out.println("Math.max(15, 32) = " + Math.max(15, 32));
// 最小值
System.out.println("Math.min(15, 32) = " + Math.min(15, 32));
// [0.0, 1.0)区间内的随机数
System.out.println("Math.random() = " + Math.random());
}
}
执行输出结果:

Math.abs(-1314) = 1314
Math.sin(Math.toRadians(30)) = 0.49999999999999994
Math.log(100) = 4.605170185988092
Math.log10(100) = 2.0
Math.sqrt(3) = 1.7320508075688772
Math.pow(2,4) = 16.0
Math.addExact(12, 13) = 25
Math.subtractExact(13, 7) = 6
Math.multiplyExact(25,8) = 200
Math.max(15, 32) = 32
Math.min(15, 32) = 15
Math.random() = 0.36067650327439227

下面是另一个示例:
public class Test14 {
public static void main(String[] args) {
double[] nums = {1.4, 1.5, 1.6, -1.4, -1.5, -1.6};
for (double num : nums) {
test(num);
}
}

private static void test(double num) {
    // 测试Math类中的ceil(double a)、floor(double a)、round(double a)方法
    System.out.println("Math.ceil(" + num + ")=" + Math.ceil(num));
    System.out.println("Math.floor(" + num + ")=" + Math.floor(num));
    System.out.println("Math.round(" + num + ")=" + Math.round(num));
}

}
执行输出结果:

Math.ceil(1.4)=2.0
Math.floor(1.4)=1.0
Math.round(1.4)=1
Math.ceil(1.5)=2.0
Math.floor(1.5)=1.0
Math.round(1.5)=2
Math.ceil(1.6)=2.0
Math.floor(1.6)=1.0
Math.round(1.6)=2
Math.ceil(-1.4)=-1.0
Math.floor(-1.4)=-2.0
Math.round(-1.4)=-1
Math.ceil(-1.5)=-1.0
Math.floor(-1.5)=-2.0
Math.round(-1.5)=-1
Math.ceil(-1.6)=-1.0
Math.floor(-1.6)=-2.0
Math.round(-1.6)=-2
说明:

本例测试了java.lang.Math类中的ceil(double a)、floor(double a)、round(double a)方法,请注意比较它们的区别。

1.4、java.math.BigInteger

Java中,基本数据类型中可以表示的整型数字最大范围是64位(long型整数),如果程序中所需要使用的整数范围超过了long型的最大范围,就需要使用java.math.BigInteger类来处理。java.math.BigInteger可以用来表示任意大小的整数。

实例化一个java.math.BigInteger类的对象时,需要使用new关键字,该类提供了几个常用的构造方法,如下:

构造方法 构造方法说明
BigInteger(String val) 将 BigInteger的十进制字符串表示形式转换为 BigInteger实例
BigInteger(String val, int radix) 将指定基数的 BigInteger的字符串表示形式转换为 BigInteger实例
BigInteger(byte[] val) 将包含 BigInteger的二进制补码表示形式的 byte数组转换为 BigInteger实例
下面是一个示例:
import java.math.BigInteger;

public class Test15 {
public static void main(String[] args) {
// 实例化BigInteger对象
BigInteger bigInteger1 = new BigInteger(“123456789123456789123456789”);
BigInteger bigInteger2 = new BigInteger(new byte[]{127,1,1,1});
BigInteger bigInteger3 = new BigInteger(“123456789123456789123456789”,10);
BigInteger bigInteger4 = new BigInteger(“01111111000000010000000100000001”,2);
// 打印它们的值
System.out.println("bigInteger1 = " + bigInteger1);
System.out.println("bigInteger2 = " + bigInteger2);
System.out.println("bigInteger3 = " + bigInteger3);
System.out.println("bigInteger4 = " + bigInteger4);
}
}
执行输出结果:

bigInteger1 = 123456789123456789123456789
bigInteger2 = 2130772225
bigInteger3 = 123456789123456789123456789
bigInteger4 = 2130772225
说明:

本例演示了java.math.BigInteger类的几种常用构造方法。java.math.BigInteger类的对象可以表示任意大小的整数。
对于java.math.BigInteger类对象的基本算数运算等操作,需要使用该类的实例成员方法。该类中常用的API如下:

方法 返回值 方法说明
abs() BigInteger 返回此BigInteger实例的绝对值
add(BigInteger val) BigInteger 返回值为 (this + val) 的BigInteger实例
subtract(BigInteger val) BigInteger 返回值为 (this - val) 的BigInteger实例
multiply(BigInteger val) BigInteger 返回值为 (this * val) 的BigInteger实例
divide(BigInteger val) BigInteger 返回值为 (this / val) 的BigInteger实例
mod(BigInteger m) BigInteger 返回值为 (this mod m) 的BigInteger实例
remainder(BigInteger val) BigInteger 返回值为 (this % val) 的BigInteger实例
pow(int exponent) BigInteger 返回值为 this的exponent次幂的BigInteger实例
max(BigInteger val) BigInteger 返回this和val中值较大的一个
min(BigInteger val) BigInteger 返回this和val中值较小的一个
toString() String 返回此BigInteger的十进制字符串表示形式
toString(int radix) String 返回给定基数中BigInteger的字符串表示形式
下面是一个示例:

package com.codeke.java.test;

import java.math.BigInteger;

public class Test16 {
public static void main(String[] args) {
// 实例化BigInteger类对象
BigInteger num1 = new BigInteger(“123456789123456789”);
BigInteger num2 = new BigInteger(“987654321987654321”);
// 测试BigInteger类常用的方法
System.out.println("num1 = " + num1);
System.out.println("num2 = " + num2);
System.out.println("num1.abs() = " + num1.abs());
System.out.println("num1.add(num2) = " + num1.add(num2));
System.out.println("num2.subtract(num1) = " + num2.subtract(num1));
System.out.println("num1.multiply(num2) = " + num1.multiply(num2));
System.out.println("num2.divide(num1) = " + num2.divide(num1));
System.out.println("num1.mod(num2) = " + num1.mod(num2));
System.out.println("num1.remainder(num2) = " + num1.remainder(num2));
System.out.println("num1.pow(num2) = " + num1.pow(2));
System.out.println("num1.max(num2) = " + num1.max(num2));
System.out.println("num1.min(num2) = " + num1.min(num2));
}
}
执行输出结果:

num1 = 123456789123456789
num2 = 987654321987654321
num1.abs() = 123456789123456789
num1.add(num2) = 1111111111111111110
num2.subtract(num1) = 864197532864197532
num1.multiply(num2) = 121932631356500531347203169112635269
num2.divide(num1) = 8
num1.mod(num2) = 123456789123456789
num1.remainder(num2) = 123456789123456789
num1.pow(num2) = 15241578780673678515622620750190521
num1.max(num2) = 987654321987654321
num1.min(num2) = 123456789123456789
说明:

本例演示了java.math.BigInteger类中abs()、add(BigInteger val)、subtract(BigInteger val)、mod(BigInteger m)、pow(int exponent)、max(BigInteger val)等众多方法,java.math.BigInteger类的对象在进行加减乘除操作时,不会有范围限制,但是运算速度比起基本数据类型的运算来说会慢一些。
下面是另一个示例:
import java.math.BigInteger;

public class Test17 {
public static void main(String[] args) {
// // 实例化BigInteger类对象
BigInteger num = new BigInteger(“9223372036854775808”);
System.out.println("num1 = " + num);

    // 获取基本数据类型的值,不保证结果准确
    System.out.println("num.byteValue() = " + num.byteValue());
    System.out.println("num.shortValue() = " + num.shortValue());
    System.out.println("num.intValue() = " + num.intValue());
    System.out.println("num.longValue() = " + num.longValue());
    System.out.println("num.floatValue() = " + num.floatValue());
    System.out.println("num.doubleValue() = " + num.doubleValue());

    // 获取基本数据类型的值,转换时如果超出范围,将直接抛出ArithmeticException异常,保证结果是准确的
    try {
        System.out.println("num.byteValueExact() = " + num.byteValueExact());
    } catch (ArithmeticException e) {
        e.printStackTrace();
    }
    try {
        System.out.println("num.shortValueExact() = " + num.shortValueExact());
    } catch (ArithmeticException e) {
        e.printStackTrace();
    }
    try {
        System.out.println("num.intValueExact() = " + num.intValueExact());
    } catch (ArithmeticException e) {
        e.printStackTrace();
    }
    try {
        System.out.println("num.longValueExact() = " + num.longValueExact());
    } catch (ArithmeticException e) {
        e.printStackTrace();
    }
}

}

执行输出结果:

num = 9223372036854775808
num.byteValue() = 0
num.shortValue() = 0
num.intValue() = 0
num.longValue() = -9223372036854775808
num.floatValue() = 9.223372E18
num.doubleValue() = 9.223372036854776E18
java.lang.ArithmeticException: BigInteger out of byte range
at java.math.BigInteger.byteValueExact(BigInteger.java:4592)
at com.codeke.java.test.Test.main(Test.java:21)
java.lang.ArithmeticException: BigInteger out of short range
at java.math.BigInteger.shortValueExact(BigInteger.java:4571)
at com.codeke.java.test.Test.main(Test.java:26)
java.lang.ArithmeticException: BigInteger out of int range
at java.math.BigInteger.intValueExact(BigInteger.java:4550)
at com.codeke.java.test.Test.main(Test.java:31)
java.lang.ArithmeticException: BigInteger out of long range
at java.math.BigInteger.longValueExact(BigInteger.java:4531)
at com.codeke.java.test.Test.main(Test.java:36)
说明:

java.math.BigInteger类同大多数包装类一样,继承自java.lang.Number类,故java.math.BigInteger类也继承并重写了java.lang.Number类中用以获取各种基本数据类型对应数值的方法。即byteValue()(未重写)、shortValue()(未重写)、intValue()、longValue()、floatValue()、doubleValue()。
上述intValue()、longValue()、floatValue()、doubleValue()方法在将java.math.BigInteger类的对象转换为基本数据类型的值时,均有可能出现java.math.BigInteger类对象表示的数字超过基本数据类型可以表示的范围的情况,此时,转换时会丢失高位信息,转换结果不一定准确。如果需要准确地转换成基本类型,可以使用java.math.BigInteger类提供的byteValueExact()、shortValueExact()、intValueExact()、longValueExact()方法,这些方法在转换时如果超出范围,将直接抛出ArithmeticException异常。

1.5、java.math.BigDecimal

先来看下面的示例:
public class Test 18{
public static void main(String[] args) {
System.out.println(0.05 + 0.01);
System.out.println(1.0 - 0.42);
System.out.println(4.015 * 100);
System.out.println(123.3 / 100);
}
}
执行输出结果:

0.060000000000000005
0.5800 0000 0000 0001
4 01.49 9999 9999 9994
1.2329999999999999
解释:

在Java中,使用基本数据类型(即float类型和double类型)的浮点数时,由于小数在转换为二进制时并不一定能用一个精确的二进制表示,大多数时候都是取一个近似值,这就造成了精度的丢失。如果再用这个二进制进行计算,计算结果的精度会进一步丢失。
通过上例可以看到,使用基本数据类型进行浮点数的处理时,极大可能存在精度丢失的风险,这在类似财务计算、地图位置经纬度计算等需要精准浮点数处理的业务场景中,无法保证程序结果的准确性。

针对上述问题,Java已经提供了解决方案,在Java中,和java.math.BigInteger类类似的,可以使用java.math.BigDecimal类的对象来表示一个任意大小且精度完全准确的浮点数。java.math.BigDecimal类也同样继承自java.lang.Number类。

实例化java.math.BigDecimal类的对象时常用的构造方法如下:

构造方法 构造方法说明
BigDecimal(BigInteger val) 将一个BigInteger实例转换成一个BigDecimal实例
BigDecimal(BigInteger val, MathContext mc) 用一个BigInteger实例和指定的上下文获得一个BigDecimal实例
BigDecimal(BigInteger unscaledVal, int scale) 用一个BigInteger实例和一个指定的小数位数获得一个BigDecimal实例
BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) 用一个BigInteger实例、一个指定的小数位数和指定的上下文获得一个BigDecimal实例
BigDecimal(double val) 用一个double值获得一个BigDecimal实例
BigDecimal(double val, MathContext mc) 用一个double值和指定的上下文获得一个BigDecimal实例
BigDecimal(int val) 用一个int值获得一个BigDecimal实例
BigDecimal(int val, MathContext mc) 用一个int值和指定的上下文获得一个BigDecimal实例
BigDecimal(long val) 用一个long值获得一个BigDecimal实例
BigDecimal(long val, MathContext mc) 用一个long值和指定的上下文获得一个BigDecimal实例
BigDecimal(String val) 用一个String对象表示的数字获得一个BigDecimal实例
BigDecimal(String val, MathContext mc) 用一个String对象表示的数字和指定的上下文获得一个BigDecimal实例
下面是一个示例:
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;

public class Test19 {
public static void main(String[] args) {
// 实例化几个BigDecimal对象
BigDecimal num1 = new BigDecimal(new BigInteger(“123456”));
BigDecimal num2 = new BigDecimal(new BigInteger(“123456”), new MathContext(2, RoundingMode.CEILING));
BigDecimal num3 = new BigDecimal(new BigInteger(“123456”), 4);
BigDecimal num4 = new BigDecimal(new BigInteger(“123456”), 4, new MathContext(2, RoundingMode.FLOOR));
BigDecimal num5 = new BigDecimal(123.456);
BigDecimal num6 = new BigDecimal(123.456, new MathContext(3, RoundingMode.UP));
BigDecimal num7 = new BigDecimal(123456);
BigDecimal num8 = new BigDecimal(123456, new MathContext(3, RoundingMode.DOWN));
BigDecimal num9 = new BigDecimal(123456L);
BigDecimal num10 = new BigDecimal(123456L, new MathContext(4, RoundingMode.HALF_UP));
BigDecimal num11 = new BigDecimal(“123456”);
BigDecimal num12 = new BigDecimal(“123456”, new MathContext(4, RoundingMode.HALF_DOWN));

    // 打印
    System.out.println("num1 = " + num1);
    System.out.println("num2 = " + num2);
    System.out.println("num3 = " + num3);
    System.out.println("num4 = " + num4);
    System.out.println("num5 = " + num5);
    System.out.println("num6 = " + num6);
    System.out.println("num7 = " + num7);
    System.out.println("num8 = " + num8);
    System.out.println("num9 = " + num9);
    System.out.println("num10 = " + num10);
    System.out.println("num11 = " + num11);
    System.out.println("num12 = " + num12);
}

}
执行输出结果:

num1 = 123456
num2 = 1.3E+5
num3 = 12.3456
num4 = 12
num5 = 123.4560000000000030695446184836328029632568359375
num6 = 124
num7 = 123456
num8 = 1.23E+5
num9 = 123456
num10 = 1.235E+5
num11 = 123456
num12 = 1.235E+5
说明:

本例演示了java.math.BigDecimal类的常用构造方法,部分构造方法需要传入一个java.math.MathContext类的实例来作为构造数字的上下文==。java.math.MathContext类常用的构造方法为MathContext(int setPrecision, RoundingMode setRoundingMode),第一个参数指定了精度,第二个参数指定了舍入模式,而舍入模式由java.math.RoundingMode枚举指定,常见的舍入模式有:
舍入模式 说明
CEILING 正无穷大方向舍入
FLOOR 负无穷大方向舍入
UP 正数向正无穷大舍入,负数向负无穷大舍入
DOWN 向 0的方向舍入
HALF_UP 向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为向上舍入的舍入模式
HALF_DOWN 向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为向下舍入的舍入模式
HALF_EVEN 向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。如果舍弃部分左边的数字为奇数,则舍入行为同 RoundingMode.HALF_UP;如果为偶数,则舍入行为同 RoundingMode.HALF_DOWN。
需要注意的是,仍然由于基本数据类型的浮点数转换为二进制时的精度丢失问题,使用BigDecimal(double val)构造方法获得的浮点数仍然会有精度丢失的情况,更好的办法是构造时使用上下文指定精度及舍入模式进行控制,或者直接使用字符串(String)形式的数字来构造,再或者使用该类的valueOf(double val)方法来获得实例,在valueOf(double val)方法中,会先将double类型的值转换为字符串,再进行构造。
对于java.math.BigDecimal类对象的基本算数运算等操作,需要使用该类的实例成员方法。该类中常用的API如下:

方法 返回值 方法说明
abs() BigDecimal BigDecimal实例的绝对值
abs(MathContext mc) BigDecimal 返回此BigDecimal实例的绝对值,并根据上下文进行舍入
add(BigDecimal augend) BigDecimal 返回值为 (this + augend) 的BigDecimal实例
add(BigDecimal augend, MathContext mc) BigDecimal 返回值为 (this + augend) 的BigDecimal实例,并根据上下文进行舍入
subtract(BigDecimal subtrahend) BigDecimal 返回值为 (this - subtrahend) 的BigDecimal实例
subtract(BigDecimal subtrahend, MathContext mc) BigDecimal 返回值为 (this - subtrahend) 的BigDecimal实例,并根据上下文进行舍入
multiply(BigDecimal multiplicand) BigDecimal 返回值为 (this * multiplicand) 的BigDecimal实例
multiply(BigDecimal multiplicand, MathContext mc) BigDecimal 返回值为 (this * multiplicand) 的BigDecimal实例,并根据上下文进行舍入
divide(BigDecimal divisor) BigDecimal 返回值为 (this / divisor) 的BigDecimal实例
divide(BigDecimal divisor, int roundingMode) BigDecimal 返回值为 (this / divisor) 的BigDecimal实例,并根据指定的舍入模式舍入
divide(BigDecimal divisor, RoundingMode roundingMode) BigDecimal 返回值为 (this / divisor) 的BigDecimal实例,并根据指定的舍入模式舍入
divide(BigDecimal divisor, int scale, int roundingMode) BigDecimal 返回值为 (this / divisor) 的BigDecimal实例,指定返回值的小数位数,并根据指定的舍入模式舍入
divide(BigDecimal divisor, int scale, RoundingMode roundingMode) BigDecimal 返回值为 (this / divisor) 的BigDecimal实例,指定返回值的小数位数,并根据指定的舍入模式舍入
divide(BigDecimal divisor, MathContext mc) BigDecimal 返回值为 (this / divisor) 的BigDecimal实例,并根据上下文进行舍入
remainder(BigDecimal divisor) BigDecimal 返回值为 (this % divisor) 的BigDecimal实例
pow(int n) BigDecimal 返回值为 this的n次幂的BigDecimal实例
pow(int n, MathContext mc) BigDecimal 返回值为 this的n次幂的BigDecimal实例,并根据上下文进行舍入
round(MathContext mc) BigDecimal 将BigDecimal实例按指定的上下文进行舍入
max(BigDecimal val) BigDecimal 返回this和val中值较大的一个
min(BigDecimal val) BigDecimal 返回this和val中值较小的一个
toString() String 返回此BigDecimal的十进制字符串表示形式
byteValueExact() byte 将此 BigDecimal实例转换为 byte值,转换时会进行检查
shortValueExact() short 将此 BigDecimal实例转换为 short值,转换时会进行检查
intValue() int 将此 BigDecimal实例转换为 int值
intValueExact() int 将此 BigDecimal实例转换为 int值,转换时会进行检查
longValue() long 将此 BigDecimal实例转换为 long值
longValueExact() long 将此 BigDecimal实例转换为 long值,转换时会进行检查
floatValue() float 将此 BigDecimal实例转换为 float值
doubleValue() double 将此 BigDecimal实例转换为 double值
下面是一个示例:

package com.codeke.java.test;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;

public class Test {
public static void main(String[] args) {
// 实例化几个BigDecimal对象
BigDecimal num1 = new BigDecimal(“123456.123456”);
BigDecimal num2 = new BigDecimal(“789.456”);

    // 测试BigDecimal的常用方法
    System.out.println("num1.abs() = " + num1.abs());
    System.out.println("num1.add(num2) = " + num1.add(num2));
    System.out.println("num1.subtract(num2) = " + num1.subtract(num2));
    System.out.println("num1.multiply(num2) = " + num1.multiply(num2));
    System.out.println("num1.divide(num2, BigDecimal.ROUND_HALF_EVEN) = " + num1.divide(num2, BigDecimal.ROUND_HALF_EVEN));
    System.out.println("num1.divide(num2, 2, RoundingMode.HALF_EVEN) = " + num1.divide(num2, 2, RoundingMode.HALF_EVEN));
    System.out.println("num2.pow(2) = " + num2.pow(2));
    System.out.println("num2.round(new MathContext(3, RoundingMode.HALF_EVEN)) = " + num2.round(new MathContext(3, RoundingMode.HALF_EVEN)));
    System.out.println("num1.max(num2) = " + num1.max(num2));
    System.out.println("num1.min(num2) = " + num1.min(num2));
    System.out.println("num1.longValue() = " + num1.longValue());
    System.out.println("num2.intValue() = " + num2.intValue());
    System.out.println("num1.doubleValue() = " + num1.doubleValue());
    System.out.println("num2.floatValue() = " + num2.floatValue());
    try {
        System.out.println("num1.multiply(num2).byteValueExact() = " + num1.multiply(num2).byteValueExact());
    } catch (ArithmeticException e) {
        e.printStackTrace();
    }
}

}
执行输出结果:

num1.abs() = 123456.123456
num1.add(num2) = 124245.579456
num1.subtract(num2) = 122666.667456
num1.multiply(num2) = 97463177.399079936
num1.divide(num2, BigDecimal.ROUND_HALF_EVEN) = 156.381259
num1.divide(num2, 2, RoundingMode.HALF_EVEN) = 156.38
num2.pow(2) = 623240.775936
num2.round(new MathContext(3, RoundingMode.HALF_EVEN)) = 789
num1.max(num2) = 123456.123456
num1.min(num2) = 789.456
num1.longValue() = 123456
num2.intValue() = 789
num1.doubleValue() = 123456.123456
num2.floatValue() = 789.456
java.lang.ArithmeticException: Rounding necessary
at java.math.BigDecimal.commonNeedIncrement(BigDecimal.java:4179)
at java.math.BigDecimal.needIncrement(BigDecimal.java:4235)
at java.math.BigDecimal.divideAndRound(BigDecimal.java:4143)
at java.math.BigDecimal.setScale(BigDecimal.java:2455)
at java.math.BigDecimal.longValueExact(BigDecimal.java:3121)
at java.math.BigDecimal.byteValueExact(BigDecimal.java:3218)
at com.codeke.java.test1.Test.main(Test.java:29)
说明:

本例演示了java.math.BigDecimal类中的常用方法,如abs()、add(BigDecimal augend)、subtract(BigDecimal subtrahend)、multiply(BigDecimal multiplicand)、divide(BigDecimal divisor, int roundingMode)、divide(BigDecimal divisor, int scale, RoundingMode roundingMode)、pow(int n)、round(MathContext mc)、max(BigDecimal val)、min(BigDecimal val)、longValue()、intValue()、doubleValue()、floatValue()、byteValueExact()等。
注意,在部分方法中,如divide(BigDecimal divisor, int roundingMode),舍入模式也可以使用java.math.BigDecimal类中的常量来指定。
浮点数的除法,经常会出现除不尽的情况,故尽量要通过参数指定精确的小数位数及舍入模式。
java.math.BigDecimal类中继承自java.lang.Number的方法(intValue()、longValue()等),也出现java.math.BigDecimal类对象表示的数字超过基本数据类型可以表示的范围的情况,此时,转换时会丢失高位信息,转换结果不一定准确。如果需要准确地转换成基本类型==,可以使用java.math.BigDecimal类提供的byteValueExact()、shortValueExact()、intValueExact()、longValueExact()方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值