BigDecimal实战

本文介绍了计算机中浮点数的表示方式以及Java中float和double类型的精度问题。重点讲解了BigDecimal类,它是不可变的、具有任意精度的十进制数,用于解决精度丢失的问题。文章还提到了BigDecimal的precision和scale属性,并与其他如BigInteger的类进行了对比,提供了实际操作中的处理建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

context

在计算机中,通常不能直接来表示小数,而是要将小数分为多个部分(二进制形式)来存储。表示实数的方法有2种:

a. 定点数表示法

b. 浮点数表示法

2种方法的区别在于小数点是否固定。在Java中,float(单精度)和double(双精度)类型的小数都是用浮点数表示法来存储在计算机中,即遵循IEEE-754标准。

通常我们都是通过字面量来赋值:

double a = 0.4;
double b = 0.3;

上面说过了,浮点数最后以二进制形式存储在计算机中,然而有些字面量(十进制数)无法精确转换为二进制形式(毕竟寄存器bit位有限):

double a = 0.4; // 无法精确转换
double b = 0.3; // 无法精确转换

double c = 0.5; // 精确转换
double d = 0.25; // 精确转换

这样一来,在定义浮点数的时候就有可能出现精度丢失,故影响到运算过程的结果:

double a = 0.4;
double b = 0.3;
double c = a - b;
System.out.println(c); // 0.10000000000000003

double c = 0.5;
double d = 0.25;
double f = d - e;
System.out.println(f); // 0.25

BigDecimal: precision & scale

java.math.BigDecimal

不可变的、具有任意精度的、有符号的十进制数。BigDecimal由2部分组成:任意精度的(不含小数)整数(unscaled value)和含32 bit位整型的小数位(scale)。当表示的数大于或等于0时,scale的值为小数点以右的位数。当表示的数为负数时,unscaled value = negative number * 10 ^ (-scale)。所以,任意由BigDecimal表示的十进制数等于 unscaledValue * 10 ^ (-scale)。


Immutable, arbitrary-precision signed decimal numbers. A BigDecimal consists of an arbitrary precision integer unscaled value and a 32-bit integer scale. If zero or positive, the scale is the number of digits to the right of the decimal point. If negative, the unscaled value of the number is multiplied by ten to the power of the negation of the scale. The value of the number represented by the BigDecimal is therefore (unscaledValue × 10 ^ (-scale)).

Examples:

string------[unscaled value, scale]

“0”      [0, 0]

“12.0”    [120, 1]

“12.3”    [123, 1]

BigDecimal有2个比较重要的属性,precision和scale,分别表示有效数的长度和小数点位数:

MathContext mathContext = new MathContext(4); // precision = 4
BigDecimal decimal = new BigDecimal("4123.51651", mathContext); 
System.out.println(decimal); // 4124
System.out.println(decimal.movePointRight(1)); // 41240

BigDecimal scaled = BigDecimal.valueOf(12.15)
    .setScale(1, RoundingMode.HALF_UP); // scale = 1; 四舍五入
System.out.println(scaled); // 12.2

还有另外一个类java.math.BigInteger,它则用于整数之间的运算。

practices

// 创建BigDecimal对象(建议使用工厂方法)
BigDecimal.valueOf(1.0d);
BigDecimal.valueOf(1L);

// 对某个小数进行四舍五入后保留指定小数位
BigDecimal.valueOf(13.15).setScale(1, RoundingMode.HALF_UP); // 13.2

// 除法运算后转换成百分比
BigDecimal.valueOf(0.20).movePointRight(2); //20

当数据库表中用decimal存储,查询后用BigDecimal接收并返回给前端时,会出现精度丢失,如(1.00 -> 1)。一般的处理都是将其转换成字符串然后返给前端。

@JsonFormat(shape = JsonFormat.Shape.STRING)
private BigDecimal decimal;

end


nonterminating 无尽的

for the sake of 为了

significand 有效数

exponent 指数,幂


add

addend /əˈdend/ 加数

augend /ˈɔːdʒend/ 被加数


subtract

minuend /ˈmɪnjʊˌend/ 被减数

subtrahend /ˈsʌbtrəˌhend/ 减数


multiply

multiplier 乘数

multiplicand 被乘数


divide

dividend 被除数

divisor 除数

quotient /ˈkwoʊʃnt/ 商


remainder /rɪˈmeɪndər/ 余数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值