您的位置:首页 > 编程语言 > Java开发

[疯狂Java]基础类库:BigDecimal(精确实数)

2016-05-22 16:14 501 查看
1. BigDecimal简介:

1) 用Java的基础类型来表示数据还是有一定的局限性的:

i. 对于整型最明显的就是存在界限问题,由于使用有限位二进制数来表示整型,必定存在上下限,不能表示更大范围的数了;

ii. 对于浮点型就不用说了,根本无法精确表示,例如一个字面值0.1也无法在底层用二进制精确表示!

2) BigDecimal——精确实数:

i. Java提供BigDecimal类来表示精确实数;

ii. 它底层使用字符串来保存数字的,而字符串的位数不受限制,这就首先突破了整型界限的问题;

iii. 其次,同样是由于用字符串来保存数字的,对于浮点数其小数部分可以精确到最低位;

2. 构造:

1) 首推用字符串来构造:毕竟本身底层即使用字符串保存的

i. BigDecimal(String val);

ii. BigDecimal(char[] val);

iii. BigDecimal(char[] val, int offset, int len);

!!分别用String和字符数组来构造,例如:BigDecimal num = new BigDecimal("0.123");

2) 当然也可以用基本类型来构造:

i. BigDecimal(int | long | double val); // 只支持这三种类型

ii. 也可以用其静态工具方法来构造:static BigDecimal BigDecimal.valueOf(long | double val); // 只支持long和double

!!但是double版本的最好不要用!!因为double本身就是不精确的,转换成BigDecimal同样是不精确的!!(转换的方法就是取其字符串表示形式)

3. 转换成基本类型:

1) 当然也允许将BigDecimal类型转换成相应的基本类型;

2) 对于整型:type typeValue[Exact](); // type支持byte、short、int、long

i. 这里转换的时候问题又两个,一个是BigDecimal表示的是实数,可能有小数点,另一个时转换成相应的整型时可能会溢出;

ii. 没有Exact的版本遇到上面两个问题没有异常,直接截断处理(这可能会导致后续程序的错误);

iii. Exact的版本遇到上面两个问题时会抛出异常!

!!通常使用第二个版本;

4. 算术运算:

1) 二元运算:BigDecimal op(BigDecimal val); // this op val

i. 加:add

ii. 减:subtract

iii. 乘:multiply

!!除法非常特殊,最后详解

2) 指数运算:BigDecimal pow(int n); // this ^ n

3) 一元运算:

i. 绝对值:BigDecimal abs();

ii. 取反(加一个负号):BigDecimal negate();

iii. 信号采样:int signum(); // 负数返回-1,正数1,0返回0

iv. 自加(自己加自己,不是加1):BigDecimal plus();

4) 除法为什么特殊:

i. BigDecimal表示精确实数,因此其进行运算之后得到的结果也希望是精确实数,精确实数经过上述的所有运算之后得到的结果必然也是精确的,但是除法就不一定了;

ii. 最简单的就是1 / 3得到的就是无限循环的0.333...,对于无限循环小数BigDecimal再精确也无法表示了,因为不可能存无限个3啊!!

iii. 考虑到这个问题,BigDecimal的除法divide就需要考虑精度问题了!

iv. 因此除法通常含有控制精度的参数;

5) 除法:

i. 完整版:BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode);

a. divisor是除数,scale是精度(小数点后保留几位),roundingMode是取舍方式;

b. 取舍方式:都是BigDecimal中定义的静态常量,常用的有

HALF_UP:四舍五入

CEILING:取上限

FLOOR:取下限

UNNECESSARY:没必要取舍,这就意味着得到的结果一定是精确的、不会有无限循环的,但是一旦有就会抛出异常!!

ii. BigDecimal divide(BigDecimal divisor, int roundingMode); // 精度使用默认值,取舍方式自己决定

iii. BigDecimal divide(BigDecimal divisor); // 精度默认,取舍方式默认是UNNECESSARY,因此小心抛出异常哦!!

6) 既然有除法,必然有模除咯!

i. 首先要知道整除(即结果只取除法结果的整数部分):BigDecimal divideToIntegralValue(BigDecimal divisor); // 定义为a \ b

ii. 接着就是模除:BigDecimal remainder(BigDecimal divisor); // 理论上就是a % b

!!但是BigDecimal表示的是实数,因此两个操作数都可能有小数点,而这里的模除是广义模除,其运算方法就是 a - (a \ b) × b,因此结果很可能也有小数点,并且也可能是负数!

7) 还有同时得到除数和余数的方法:BigDecimal[] divideAndRemainder(BigDecimal divisor); // 把上面两个方法分别放在[0]和[1]中一块儿返回(先\结果,后%结果)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: