BigDecimal 简单使用

2023-05-16

目录

为什么使用BigDecimal

解决方案

构造方法

类型转换

double 转 BigDecimal

BigDecimal 转 String

BigDecimal 转 double/int/long等

加减乘除取余

divide

舍入模式

比较大小

格式化(DecimalFormat)

小结


为什么使用BigDecimal

  • 1.float和double类型的主要设计目标是为了科学计算和工程计算。他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的。然而,它们没有提供完全精确的结果

  • 2.作为移动端,经常调用后端接口,返回参数类型由后端决定。当我们使用double去接收并使用可能产生以下问题。

    public void dfFormat() {
        double number =1000000000000.0;
        //变成了科学计数法
        log("number直接打印->"+number);
        log("numberString.valueOf->"+String.valueOf(number));
    }

输出结果

number直接打印->1.0E12,这里直接变成了科学计数法。

numberString.valueOf->1.0E12,转String也是科学计数法。

解决方案

  • 1、如果仅展示不需要后续做处理(保留小数位、加减乘除等),可以让后端返回String类型。

  • 2、使用BigDecimal

    • 1.直接使用BigDecimal替代double接收数据。

    • 2.将double转成BigDecimal。

    public void dfFormat() {
        double number =1000000000000.0;
        //toPlainString
        log("numberDecimal-> "+BigDecimal.valueOf(number).toPlainString());
    }

输出结果

numberDecimal-> 1000000000000,从结果可以看出,数据显示正常了。

double转BigDecimal,使用的是BigDecimal.valueOf(number) ,而不是 new BigDecimal(number)

BigDecimal转成String,使用的是toPlainString() ,而不是toString()

构造方法

BigDecimal提供的比较常用的是下面几种方法:

  • 1.public BigDecimal(String val):将 String 表示形式转换成 BigDecimal(推荐使用)

  • 2.public BigDecimal(int val):将 int 表示形式转换成 BigDecimal

  • 3.public BigDecimal(double val):将 double 表示形式转换为 BigDecimal(不推荐使用)

    public void dfFormat() {
        BigDecimal a = new BigDecimal("10");
        BigDecimal b = new BigDecimal(5);
        BigDecimal k = new BigDecimal(-16.0034);
    }

输出结果

 a-> 10
 b-> 5
 k-> -16.00339999999999918145476840436458587646484375

原因:float和double类型的主要设计目标是为了科学计算和工程计算。他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的。然而,它们没有提供完全精确的结果,所以不应该用于要求精确结果的场合。

类型转换

注意:double转BigDecimal使用new BigDecimal()的方式会造成精度丢失。怎么解决?看下面的类型转换。

double 转 BigDecimal

精度丢失解决方案:

  • 1:new BigDecimal(String.valueOf(number2));

  • 2:BigDecimal.valueOf(number2);

    public void dfFormat() {
  double number2 =-16.0034;
        log("number2直接打印->"+number2);
        //double转BigDecimal导致丢失精度
        log("number2Decimal-> "+new BigDecimal(number2).toPlainString());

        //精度丢失解决方案:
        log("精度丢失String.valueOf-> "+new BigDecimal(String.valueOf(number2)).toPlainString());
        log("精度丢失BigDecimal.valueOf-> "+BigDecimal.valueOf(number2).toPlainString());
    }

输出结果

精度丢失String.valueOf-> -16.0034
精度丢失BigDecimal.valueOf-> -16.0034

BigDecimal 转 String

    public void dfFormat() {
        double number =1000000000000.0;
        //toString和toPlainString
        log("toString-> "+new BigDecimal(String.valueOf(number)).toString());
        log("toString-> "+BigDecimal.valueOf(number).toString());
        log("toPlainString-> "+ new BigDecimal(String.valueOf(number)).toPlainString());
        log("toPlainString-> "+BigDecimal.valueOf(number).toPlainString());

两种方式对比toString和toPlainString的区别。

输出结果

toString-> 1.0E+12
toString-> 1.0E+12
toPlainString-> 1000000000000
toPlainString-> 1000000000000

注意:很多人肯定习惯使用toString()了,但在BigDecimal这里就需要注意了,要使用toPlainString()。

BigDecimal 转 double/int/long等

        //如:BigDecimal转double
        BigDecimal b = new BigDecimal(5);
        //doubleValue-> 5.0
        log("doubleValue-> "+b.doubleValue());

加减乘除取余

BigDecimal 提供的方法:

    public BigDecimal add(BigDecimal augend) {}//加
    public BigDecimal subtract(BigDecimal subtrahend) {}//减
    public BigDecimal multiply(BigDecimal multiplicand) {}//乘
    public BigDecimal divide(BigDecimal divisor) {}//除(不推荐使用)
    public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) {}//除(推荐使用)
    public BigDecimal[] divideAndRemainder(BigDecimal divisor) {}//取余
        //加减乘除
        BigDecimal a = new BigDecimal("10");
        BigDecimal b = new BigDecimal(5);
        log("10 + 5-> "+a.add(b).toPlainString());
        log("10 - 5-> "+a.subtract(b).toPlainString());
        log("10 * 5-> "+a.multiply(b).toPlainString());
        log("10 / 5-> "+a.divide(b).toPlainString());
        
        BigDecimal e = BigDecimal.valueOf(5.34178);
        BigDecimal f = BigDecimal.valueOf(3.12456);
        //e.divide(f)直接报错
//        e("e / f-> "+e.divide(f).toPlainString());
        log("e / f-> "+e.divide(f,3,BigDecimal.ROUND_HALF_UP).toPlainString());
        //取余
        BigDecimal []h = e.divideAndRemainder(f);
        log("e / f 取余 整-> "+h[0]+"余->"+h[1]);
        BigDecimal []j = a.divideAndRemainder(b);
        log("10 / 5 取余 整-> "+j[0]+"余->"+j[1]);

输出结果

10 + 5-> 15
10 - 5-> 5
10 * 5-> 50
10 / 5-> 2
e / f-> 1.710
e / f 取余 整-> 1余->2.21722
10 / 5 取余 整-> 2余->0

注意:

  • 1.为什么不推荐使用divide(BigDecimal divisor)?当 BigDecimal除法可能出现不能整除的情况,就会发送运行时异常:java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result。

  • 2.跟String一样, BigDecimal页是不可变的,在进行每一步运算时,都会产生一个新的对象。

divide

e.divide(f,3,BigDecimal.ROUND_HALF_UP)

参数解释:

  • divisor:除数

  • scale:表示小数点保留位数

  • roundingMode:表示舍入模式

舍入模式

我们一般舍入模式采取的是ROUND_HALF_UP,默认的也是ROUND_HALF_UP。

  • ROUND_CEILING //向正无穷方向舍入

  • ROUND_UP //不管保留数字后面是大是小 (0 除外) 都会进1

  • ROUND_DOWN //舍去制,截断操作,后面所有数字直接去除。结果会向原点方向对齐

  • ROUND_FLOOR //向负无穷方向舍入

  • ROUND_HALF_EVEN //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP,如果是偶数,使用ROUND_HALF_DOWN

  • ROUND_HALF_UP //四舍五入:向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 3.15保留一位小数结果为3.2

  • ROUND_HALF_DOWN //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如3.15 保留一位小数结果为3.1

  • ROUND_UNNECESSARY //计算结果是精确的,不需要舍入模式

比较大小

        //比较大小
        BigDecimal u = new BigDecimal("1");
        //BigDecimal.ZERO==0;
        if(u.compareTo(BigDecimal.ZERO)==-1){
            log("u 小于 0");
        }
        if(u.compareTo(BigDecimal.ZERO)==0){
            log("u 等于 0");
        }
        if(u.compareTo(BigDecimal.ZERO)==1){
            log("u 大于 0");
        }
        BigDecimal um = new BigDecimal("-1");
        BigDecimal uzero = new BigDecimal("0");
        if(um.compareTo(BigDecimal.ZERO)==-1){
            log("um 小于 0");
        }
        if(uzero.compareTo(BigDecimal.ZERO)==0){
            log("uzero 等于 0");
        }

输出结果

 u 大于 0
 um 小于 0
 uzero 等于 0

BigDecimal 提供了三个常量分别为0,1,10。使用方法如上面的BigDecimal.ZERO(0)。

    //0
    public static final BigDecimal ZERO = new BigDecimal(0, 0);
    //1
    public static final BigDecimal ONE = new BigDecimal(1, 0);
    //10
    public static final BigDecimal TEN = new BigDecimal(10, 0);

格式化(DecimalFormat)

比如我们常用的保留小数位、补零、去零。

        DecimalFormat df2 = new DecimalFormat("######0.##");
        DecimalFormat df3 = new DecimalFormat("######0.###");
        //保留2位小数,不补零
        log(df2.format(3.1415927));//3.14
        log(df2.format(3.1));//3.14
        //保留3位小数,不补零
        log(df3.format(3.1415927));//3.142,默认四舍五入
        log(df2.format(3.1));//3.14
        DecimalFormat df22 = new DecimalFormat("######0.00");
        DecimalFormat df32 = new DecimalFormat("######0.000");
        //保留2位小数,补零
        log(df22.format(3.2));//3.20
        //保留3位小数,补零
        log(df32.format(3.2));//3.200
        //去掉BigDecimal后无用的零
        BigDecimal g = new BigDecimal("0.1000");
        log(g.stripTrailingZeros().toPlainString());//0.1
        
        double pi = 3.1415927;
        System.out.print(pi);
        //取一位整数
        log(new DecimalFormat("0").format(pi));//3
        //取一位整数和两位小数
        log(new DecimalFormat("0.00").format(pi));//3.14
        //取两位整数和三位小数,整数不足部分以0填补。
        log(new DecimalFormat("00.000").format(pi));// 03.142
        //取所有整数部分
        log(new DecimalFormat("#").format(pi));//3
        //以百分比方式计数,并取两位小数
        log(new DecimalFormat("#.##%").format(pi));//314.16%
        long c = 299792458;//光速
        //每三位以逗号进行分隔。
        log(new DecimalFormat(",###").format(c)); //299,792,458
        // 将格式嵌入文本光速大小为每秒299,792,458米。
        log(new DecimalFormat("光速大小为每秒,###米。").format(c)); 

小结

  • 1.double解决不了的时候使用BigDecimal。

  • 2.尽量使用参数类型为String的构造函数。

  • 3.double转BigDecimal时,不要使用new BigDecimal()。

  • 4.BigDecimal转String时,使用toPlainString()而不是toString()。

  • 5.除法运算,需要考虑除不尽的情况。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

BigDecimal 简单使用 的相关文章

  • p2p数据分析

    大数据在许多国家具有战略意义 xff0c 其原因不仅在少数巨头公司的应用 xff0c 而是大 中 小 微企业乃至个人 xff0c 都能利用大数据来创造新的价值 而互联网本身就是一个大数据的金矿 xff0c 利用它创造价值 xff0c 是时代
  • 关于The GPG keys listed for the "***" repository are already installed but they are not corret

    这个问题是在自己制作的repo源码库的时候出现的 xff0c 从字面上理解 xff0c 是 为 源码仓库出示的GPG密钥已经安装 xff0c 但不正确 首先 xff0c GPG密钥存在的目的是处于安全和规范考虑 xff0c RedHat在发
  • __stack_chk_fail问题分析

    一 问题 进程收到SIGABRT 信号异常退出 xff0c 异常调用栈显示 stack chk fail Build fingerprint 39 Pico A7H10 PICOA7H10 10 5 5 0 smartcm 16769120
  • 十套精美个人博客网站模板

    文件资源 点击下载 展示在下方 xff0c 点击你想下载的文件 xff0c 然后点击普通下载就能下载了 紫色的图片博客个人页面模板 红色的微博社交平台HTML模板 响应式生活博客设计网站HTML5模板 程序员个人博客模板 响应式的互联网IT
  • 高性能无锁环形队列 Disruptor

    Disruptor 环形队列 JLog 秒级百G级日志搜集 传输 存储解决方案 高性能无锁队列 Disruptor 高性能队列 Disruptor 使用教程 高性能队列Disruptor框架的详细说明与实战使用 SpringBoot 并发框
  • ubuntu20.04更换阿里的软件源

    新安装的ubuntu20 04的软件源是使用的国外的源 xff0c 因此在使用apt安装软件时速度并不怎么快 xff0c 建议大家更换为国内的源 xff0c 这样在使用apt安装软件时速度会有明显的提升的 ubuntu20 04 apt的配
  • mpi运行窗口无反应或者闪退

    原因有三 1 xff0c 服务未启动 2 xff0c 系统防火墙拦截
  • Newtonsoft.Json使用,C# Json文件读取,写入

    用学校作为例子 xff0c 有学校名称 xff0c 学校下面有班级 xff0c 班级有名字 xff0c 班级下面有学生 xff0c 这里面有数组 xff0c 有字段 using System using System Collections
  • Motrix全能下载工具使用

    Motrix是一款界面简约 功能丰富 专业可靠的全能下载工具 先下载 CSDN下载 Motrix zip下载 官方下载地址 Motrix 打开Motrix xff0c 将种子文件放到这里 开始下载
  • ActiveMQ-JMS(五):ObjectMessage的安全问题

    安全问题 按照apache官网的说明 xff0c 为了避免收到恶意代码 xff0c 引入了安全机制 xff0c 只允许指定的包里的对象能够被传输 原文如下 xff1a ObjectMessage objects depend on Java
  • 剑指offer 03

    span class token keyword class span span class token class name Solution span span class token punctuation span span cla
  • 「得印度者,得天下」聊聊你不知道的印度在线视频江湖

    印度 xff0c 一个神奇古老的国度 千百年来 xff0c 恒河水鉴证了古印度王朝的兴衰更迭 xff0c 壮丽的历史文化 xff0c 和印度文明缘起缘灭的生死轮回 时光飞转 xff0c 来到公元 2018年 恒河水波澜不惊一切如昨 xff0
  • Trinity简介(1)--用于无参考基因组的转录组de novo组装

    一 Trinity简介 Trinity xff0c 是由 the Broad Institute 开发的转录组de novo组装软件 xff0c 由三个独立的软件模块组成 xff1a Inchworm Chrysalis和Butterfly
  • Trinity进行转录组组装(2))

    1 Trinity进行转录组组装 Trinity进行转录组组装的典型命令如下 opt biosoft trinityrnaseq r20131110 Trinity pl seqType fq JM 50G left sample1 1 c
  • python的两种退出方式

    os exit vs sys exit 转自 xff1a http www cnblogs com gaott archive 2013 04 12 3016355 html 概述 python的程序有两种退出方式 xff1a os exi
  • R语言数据类型转化

    R语言数据类型转化 转自 xff1a http www wangluqing com 2014 09 10 r share34 有时候 xff0c 对于一些问题 xff0c 需要进行数据类型之间的转换 R提供了基本类型转换函数以解决数据类型
  • ubuntu20.04安装中文输入法

    虽然搜狗的官网已经宣传说已经支持2004 2010 xff0c 但是支持的并不完美 xff0c 闪退 xff0c 打不出字各种问题不断 xff0c 所以本文带领大家安装几款能够正常使用的中文输入法 但是正在我要发这篇博客的时候 xff0c
  • R语言做柱状图

    R语言做柱状图 转自 xff1a http www phperz com article 16 0102 180120 html 条形图代表在与条成比例的变量的值的长度矩形条数据 R使用函数barplot 来创建柱状图 R能够绘制柱状图垂直
  • R语言 PCA(主成分分析)

    R语言 PCA 转自 xff1a http www cnblogs com longzhongren p 4300593 html 1 关键点 综述 xff1a 主成分分析 因子分析 典型相关分析 xff0c 三种方法的共同点主要是用来对数
  • 使用Pandas对数据进行筛选和排序

    使用Pandas对数据进行筛选和排序 转自 xff1a http bluewhale cc 2016 08 06 use pandas filter and sort html 筛选和排序是Excel中使用频率最多的功能 xff0c 通过这

随机推荐

  • linux 下安装blat软件

    linux 下安装blat软件 blat是一款很经典的比对工具 xff0c 与blast相比 xff0c 具有速度快 共线性输出比对结果等优点 但是 xff0c blat源码包里面的README文件写得很不清楚 xff0c 这里 xff0c
  • 基于统计的压缩算法:游程编码

    原网址 xff1a http www cnblogs com xudong bupt p 3761417 html 基于统计的压缩算法 xff1a 游程编码 1 游程编码概念 游程编码又称 运行长度编码 或 行程编码 xff0c 是一种统计
  • BWT (Burrows–Wheeler_transform)数据转换算法

    原网址 xff1a https blog csdn net luanzheng 365 article details 78575429 BWT Burrows Wheeler transform 数据转换算法 1 什么是BWT 压缩技术主
  • pip使用豆瓣的镜像源

    抄自 xff1a https www cnblogs com ZhangRuoXu p 6370107 html pip使用豆瓣的镜像源 豆瓣镜像地址 xff1a https pypi douban com simple 虽然用easy i
  • PyVCF

    抄自 xff1a https www cnblogs com nkwy2012 p 9204088 html vcf文件的全称是variant call file xff0c 即突变识别文件 xff0c 它是基因组工作流程中产生的一种文件
  • 【Kotlin 初学者】扩展-享受编程

    作者简介 xff1a CSDN博客专家 华为云 云享专家认证 系列专栏 xff1a Kotlin 初学者 学习交流 xff1a 三人行必有我师焉 xff1b 择其善者而从之 xff0c 其不善者而改之 目录 一 介绍 二 扩展函数 2 1
  • 【Kotlin 初学者】函数式编程

    作者简介 xff1a CSDN博客专家 华为云 云享专家认证 系列专栏 xff1a Kotlin 初学者 五星好评 xff1a 左侧点一下 网页端 xff0c 移动端 xff1a https bbs csdn net topics 6039
  • centos8.5 更新失败

    今天使用yum makecache的时候出现了Error Failed to download metadata for repo 39 base 39 Cannot download repomd xml Cannot download
  • 【Kotlin 初学者】Java和Kotlin互操作

    作者简介 xff1a CSDN博客专家 华为云 云享专家认证 系列专栏 xff1a Kotlin 初学者 五星好评 xff1a 左侧点一下 网页端 xff0c 移动端 xff1a https bbs csdn net topics 6039
  • Kotlin 基础知识汇总(知识与实践相结合)

    2个月的时间总算把 Kotlin 的基础知识写完了 xff0c 下面咱们看看具体内容 xff1a 学习 Kotlin 的必要性 Kotlin 初学者 为什么要学Kotlin Kotlin 初学者 打牢基础的重要性 运行环境 Kotlin 初
  • HashMap的产生与原理

    一 HashMap的诞生 1 1 数组 数组 xff1a 一片物理上连续的大小确定的储存空间 好处 xff1a 根据下标快速的查找和修改里面的内容 缺点 xff1a 大小确定 xff0c 无法修改 添加新的元素或者删除元素比较麻烦 数组的静
  • Android 数据存储(一)-文件存储

    目录 一 数据存储概念 二 应用程序专属文件存储 2 1 访问持久文件 2 2 将数据存储到文件 2 3 从文件中读取数据 2 4 查看文件列表 2 5 删除文件 三 缓存文件 cache目录下 3 1 创建缓存文件 3 2 删除文件 四
  • 回顾2021,展望2022 | 年终总结

    你付出多少努力 xff0c 就必有多少收获 一 回顾 2021 2021 年输出109篇文章 xff0c 收获 xff1a 博客专家认证 Android领域新星创作者认证 博客之星Top50 同时也在问答模块解决了部分小伙伴的问题 xff0
  • Android 数据存储(二)-SP VS DataStore VS MMKV

    一 SharedPreferences 不同于文件的存储方式 xff0c 如果要保存的键值集合相对较小 xff0c 则应使用SharedReferences API SharedReferences对象指向一个包含键值对的文件 xff0c
  • Jetpack DataStore 你总要了解一下吧?

    目录 一 DataStore 介绍 Preferences DataStore 和 Proto DataStore 二 Preferences DataStore 2 1 添加依赖 2 2 使用 Preferences DataStore
  • Android 数据存储(四)-Room

    目录 一 概述 1 1 描述 1 2 主要部件 二 创建 Room 2 1 添加依赖项 2 2 创建数据实体 2 2 1 设置 tableName or name 属性 2 2 2 设置主键 2 2 3 忽略字段 2 3 创建数据访问对象
  • Android 抛弃IMEI改用ANDROID_ID

    介绍 之前一直使用IMEI作为唯一标识符 xff0c 缺点就是需要权限 xff1a Android 10以前 xff0c 需要READ PHONE STATE权限 Android 10限制 xff0c 需要READ PRIVILEGED P
  • Android 单例模式必知必会

    目录 一 概念 1 1 单例类 1 2 优缺点 1 2 1 优点 1 2 2 缺点 二 创建单例模式的方法 2 1 饿汉式 2 2 懒汉式 2 2 1 懒汉式 非线程安全 2 2 2 懒汉式 线程安全 2 3 双重检验锁 2 4 静态内部类
  • 使用netinstall重置MIKROTIK RouterOS

    相信查看本文的读者手头应该有一台Mikrotik的路由产品 xff0c 本文中出现的RouterOS是指笔者拥有的一台家庭版路由器 非Routeros玩家可以忽略本文 下图就是笔者正在使用的一个Routeros路由器 我们在给Routero
  • BigDecimal 简单使用

    目录 为什么使用BigDecimal 解决方案 构造方法 类型转换 double 转 BigDecimal BigDecimal 转 String BigDecimal 转 double int long等 加减乘除取余 divide 舍入