BigDecimal和BigInteger

Stella981
• 阅读 641

在看《阿里巴巴开发手册》里面提到浮点数之间的等值判断不要用 ==,而是指定误差范围或用BigDecimal,然后才记忆起备忘录里BigDecimal还没写呢,就这篇幅写了一星期,因为实习完全没有时间啊啊啊啊啊啊啊啊

1. BigDecimal介绍

背景

我们知道计算机都是以二进制的形式存储数据的,而我们日常则是使用十进制,那么我们的 数字 存进计算机则需一个进制转换的过程,这过程就会损失精度的,就导致浮点数不能用等值判断

原因

十进制的0.1转换 成二进制为 0.00011001...,是无限小数,计算机存不下只能截取。后面这截取的无限小数还原成十进制就会损失精度不准确,不能用等值判断了

救星

BigDecimal的横空出世是为了解决浮点数的精度问题,其全限定类名为 java.math.BigDecimal,BigDecimal是一个对象,代表着不变的,任意精度的带符号的十进制数字,我们要使用该对象的方法来进行加减乘除的操作

原理

既然十进制小数转成二进制会损失精度,那么把十进制小数扩大成整数再转成二进制则会保持精度了

2. BigDecimal基本使用

2.1 常见构造方法

方法

描述

BigDecimal(int val)

将int转换成BigDecimal

BigDecimal(int val, MathContext mc)

根据上下设置进行舍入

BigDecimal(long val)

将long转换成BigDecimal

BigDecimal(double)

将double转换成BigDecimal

BigDecimal(String)

将String转换成BigDecimal

MathContext(int setPrecision, RoundingMode setRoundingMode)

上下文取舍(精度,舍入模式)

阿里手册规约:禁止使用构造方法 BigDecimal(double)的方式把 double 值转化为 BigDecimal 对象

BigDecimal num1 = new BigDecimal(0.1);
BigDecimal num2 = new BigDecimal("0.1");

System.out.println(num1);    // 0.1000000000000000055511151231257827021181583404541015625
System.out.println(num2);    // 0.1

因为浮点数并不是一个准确的值,而String类型的就确定

2.2 常用方法

方法

描述

abs()

返回一个绝对值BigDecimal对象

scale()

小数位数,包含末尾零。返回负数表示是一个正数,且有负数位0

stripTrailingZeros()

除去末尾的零,包含整数

add(BigDecimal augend)

被加数

add(BigDecimal augend, MathContext mc)

根据上下文取舍

subtract(BigDecimal subtrahend)

被减数

multiply(BigDecimal multiplicand)

被乘数

divide(BigDecima divisor, int roundingMode)

被除数,要指定上下文取舍,否则报错

divideAndRemainder(BigDecimal divisor)

求余

compareTo(BigDecimal val)

比较数值大小,equals要求scale()相同,且值相同

toString()

转成字符串

intValue()

转成整型

longValue()

转成长整型

BigDecimal num1 = new BigDecimal("0.01234");
BigDecimal num2 = new BigDecimal("0.56789");

-------------------------------------------------------------------

System.out.println(num1.add(num2));
System.out.println(num1.subtract(num2));
// 小数保留6位,四舍五入
System.out.println(num1.multiply(num2,new MathContext(6, RoundingMode.HALF_UP)));
// 小数保留4位,直接截取
System.out.println(num1.divide(num2,new MathContext(4,RoundingMode.DOWN)));

// 0.58023
// -0.55555
// 0.00700776
// 0.02172
    
-------------------------------------------------------------------    
    
BigDecimal num1 = new BigDecimal("0.123");
BigDecimal num2 = new BigDecimal("0.123000");

System.out.println(num1.equals(num2));
System.out.println(num1.compareTo(num2));

// false
// 0

除法存在除不尽的情况,所以一定要使用上下文取舍器

BigDecimal比较用compareTo,而equals要求scale()即小数位数相同

ArithmeticException常见的算数异常

3. BigInteger

Java原生提供的最大整型是长整型,占8字节64位,范围是-9223372036854775808 ~ 9223372036854775807,如果超过了这个范围,那么可以用不可变的BigInteger对象,其原理是内部使用 int[] 数组来模拟大数

3.1 常见构造函数

函数

描述

BigInteger(byte[] val)

BigInteger(String) val)

3.2 常见方法

方法

描述

add(BigInteger) val)

加法

subtract(BigInteger val)

BigInteger num1 = new BigInteger("1234567890");
System.out.println(num1.pow(5));    // 2867971860299718107233761438093672048294900000

BigInteger num2 = new BigInteger("123456");
long num3 = num2.longValue();
System.out.println(num3);    // 123456

我的博客即将同步至 OSCHINA 社区,这是我的 OSCHINA ID:osc_45632688,邀请大家一同入驻:https://www.oschina.net/sharing-plan/apply

本文分享 CNBlog - Howlet。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
java.math.BigDecimal类的用法
在java中提供了大数字的操作类,即java.math.BinInteger类和java.math.BigDecimal类。这两个类用于高精度计算,其中BigInteger类是针对大整数的处理类,而BigDecimal类则是针对大小数的处理类。下边我们介绍BigDecimal类:BigDecimal的实现利用到了BigInteger,不同的是Big
Wesley13 Wesley13
2年前
Java:利用BigDecimal类巧妙处理Double类型精度丢失
本篇要点简单描述浮点数十进制转二进制精度丢失的原因。介绍几种创建BigDecimal方式的区别。整理了高精度计算的工具类。学习了阿里巴巴Java开发手册关于BigDecimal比较相等的规定。经典问题:浮点数精度丢失精度丢失的问题是在其他计算机语言中也都会出
Stella981 Stella981
2年前
BigDecimal与Long、int之间的相互转换
在实际开发过程中BigDecimal是一个经常用到的数据类型,它和int、Long之间可以相互转换。转换关系如下代码展示:一、int转换成BigDecimal数据类型//int转换成bigDecimal类型publicstaticBigDecimalintToBigDecim
Wesley13 Wesley13
2年前
Java开发笔记(三十)大小数BigDecimal
前面介绍的BigInteger只能表达任意整数,但不能表达小数,要想表达任意小数,还需专门的大小数类型BigDecimal。如果说设计BigInteger的目的是替代int和long类型,那么设计BigDecimal的目的便是替代浮点型float和双精度型double了。正如它的兄弟BigInteger一般,BigDecimal不存在什么数值范围限制,无论是
Wesley13 Wesley13
2年前
JDK8 BigDecimal API
第三篇先介绍以BigInteger为构造参数的构造器1publicBigDecimal(BigIntegerval){//根据BigInteger创建BigDecimal对象2scale0;//BigInteger为整数因此有效小数位数为03intVal
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这