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/ 余数