Java基础系列:数据精度float,double,BigDecimal

1 浮点数据

浮点数据有单精度浮点数据和双精度浮点数据,对应Java中的基础数据类型为:
float和double,数据描述如下表:

序号数据类型描述有效位
1float单精度8位
2double双精度17位

float和double的有效数据位数是全部数据的位数,而不是小数点后面的位数,因此会出现数据精度丢失的问题。解析如下图:

在这里插入图片描述

图1.1 float有效数字

由图1.1可知,float的有效数字为8位,是所有数字组成的8位,即:

f l o a t 有效数字位数 = 小数点前面的数字位数 + 小数点后面的数字位数 float有效数字位数=小数点前面的数字位数+小数点后面的数字位数 float有效数字位数=小数点前面的数字位数+小数点后面的数字位数

而不是指小数点后面的有效数字位数,因此,当,需要使用保留小数点后3位或更多位数的需求时,小数点前面的数字位数达6位以上,小数点后最多保留两位,因此会出现数据精度丢失。

在这里插入图片描述

图1.2 double有效数字

由图1.2可知,double的有效数字为17位,是所有数字组成的17位,即:
d o u b l e 有效数字位数 = 小数点前面的数字位数 + 小数点后面的数字位数 double有效数字位数=小数点前面的数字位数+小数点后面的数字位数 double有效数字位数=小数点前面的数字位数+小数点后面的数字位数

同样,如果小数点前面数据过多,仍会导致数据精度降低。

1.1 有效位测试

package function;

import java.math.BigDecimal;
import java.util.logging.Logger;

import static common.constant.DigitalConstant.THREE;

/**
 * 数据计算.
 *
 * @author xindaqi
 * @date 2021-05-13 13:44
 */
public class DataProcessTest {

    private static final Logger logger = Logger.getLogger("DataProcessTest");

    public static void main(String[] args) {

        double a = 10.123456789012345678;
        logger.info("双精度数据:" + a);
        float b = 1.12345678f;
        logger.info("单精度数据:" + b);
    }
}

1.2 结果与解析

运行结果:

五月 14, 2021 10:22:23 上午 function.DataProcessTest main
信息: 双精度数据:10.123456789012346
五月 14, 2021 10:22:23 上午 function.DataProcessTest main
信息: 单精度数据:1.1234568

由运行结果可知,

  • float有效位:8位;
  • double有效位:17位;
  • float数据在第8位进行四舍五入;
  • double数据在第17位四舍五入。

2 BigDecimal

为解决数据精度丢失问题,Java提供了BigDecimal保证数据精度,并在计算时可以定制小数点后面精确位数。
源码中的取舍案例如下图所示:
在这里插入图片描述

2.1 Usage

package function;

import java.math.BigDecimal;
import java.util.logging.Logger;

import static common.constant.DigitalConstant.THREE;

/**
 * 数据计算.
 *
 * @author xindaqi
 * @date 2021-05-13 13:44
 */
public class DataProcessTest {

    private static final Logger logger = Logger.getLogger("DataProcessTest");

    public static void main(String[] args) {

        BigDecimal num1 = new BigDecimal("0.01");
        BigDecimal num2 = new BigDecimal("0.003");
        BigDecimal num3 = new BigDecimal("4.8929183");

        logger.info("BigDecimal加法:" + num1.add(num2));
        logger.info("BigDecimal减法:" + num1.subtract(num2));
        logger.info("BigDecimal乘法:" + num2.multiply(num3));
        logger.info("BigDecimal除法:" + num3.divide(num2, THREE, BigDecimal.ROUND_HALF_UP));
    }
}

2.2 结果与解析

运行结果:

五月 14, 2021 10:22:23 上午 function.DataProcessTest main
信息: BigDecimal加法:0.013
五月 14, 2021 10:22:23 上午 function.DataProcessTest main
信息: BigDecimal减法:0.007
五月 14, 2021 10:22:23 上午 function.DataProcessTest main
信息: BigDecimal乘法:0.0146787549
五月 14, 2021 10:22:23 上午 function.DataProcessTest main
信息: BigDecimal除法:1630.973

由运行结果可知,

  • BigDecimal进行加减乘计算时,默认保留了所有数据,小数点后有几位即保留几位
  • BigDecimal进行除法计算时,需要指定小数点后保留的有效数据位数和数据取舍的规则

2.3 数据取舍规则

BigDecimal提供了8中数据取舍规则,详细结束如下表

序号取舍规则描述
1ROUND_UP小数点后数字大于0即进位
2ROUND_DOWN小数点后数字全部舍弃,置为0
3ROUND_CEILING数字大于0,即进位,数字小于0则,小数点后数字全部舍弃,置为0
4ROUND_FLOOR数字小于0,即进位,数字大于0,小数点后数字全部舍弃,置为0
5ROUND_HALF_UP小数点后数字四舍五入,大于等于5进位
6ROUND_HALF_DOWN小数点后数字五舍六入,大于等于6进位
7ROUND_HALF_EVEN小数点后数字四舍六入五考虑,五前为偶舍弃,五前为奇进位
8ROUND_UNNECESSARY不需要舍入

按照取舍规则取数样例如下表所示,参考:java.math.RoundingMode。

序号样例数字UPDOWNCEILINGFLOORHALF_UPHALF_DOWNHALF_EVEN
15.56565656
22.53232322
31.62121222
41.12121111
51.01111111
6-1.0-1-1-1-1-1-1-1
7-1.1-2-1-1-2-1-1-1
8-1.6-2-1-1-2-2-2-2
9-2.5-3-2-2-3-3-2-2
10-5.5-6-5-5-6-6-5-6

【参考文献】
[1]https://www.cnblogs.com/maoxiuying/p/8522241.html
[2]https://blog.csdn.net/androidstar_cn/article/details/52916489
[3]https://blog.csdn.net/mqdxiaoxiao/article/details/88937674
[4]https://blog.csdn.net/ratter/article/details/84611558
[5]https://zhidao.baidu.com/question/1926154311505686867.html

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天然玩家

坚持才能做到极致

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值