61从零开始学Java之处理大数字相关的类有哪些?

news2024/11/25 5:50:45

作者:孙玉昌,昵称【一一哥】,另外【壹壹哥】也是我哦

千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者

前言

我们知道,在现实世界里,实际上数字是有无穷个的,就比如0和1之间,你说有多少个数字?无数个!谁也不知道有多少个吧。但是在计算机中,数字的个数其实是有限的,因为计算机有存储空间的限制,所以实际上无论是整数还是浮点数,都是有最大范围的。比如在Java中,整型的最大范围是64位的long型整数。但是有的小伙伴问了,如果我们使用的整数超过了long型的范围怎么办?此时,我们可以通过软件来模拟一个大整数或大浮点数。

在Java中提供了两个用于大数字运算的类,分别是java.math.BigInteger类 和 java.math.BigDecimal类。这两个类都可以用于高精度计算,BigInteger类是针对整型大数字的处理类,而BigDecimal类是针对大小数的处理类,我们可以用它们来表示任意大小的整数和浮点数。接下来壹哥再带大家来学习一下,在Java中如何处理大数字。

-----------------------------------------------前戏已做完,精彩即开始---------------------------------------------

全文大约【3800】字,不说废话,只讲可以让你学到技术、明白原理的纯干货!本文带有丰富的案例及配图视频,让你更好地理解和运用文中的技术概念,并可以给你带来具有足够启迪的思考......

配套开源项目资料

Github:

GitHub - SunLtd/LearnJava

Gitee:

一一哥/从零开始学Java

一. BigInteger类

1. 简介

壹哥在之前给大家讲解8种基本类型时就说过,不同的数据类型,有不同的取值范围,我们再通过下表回顾一下:

类型

所占字节(byte)

所占位数(bit)

取值范围

byte

1

8

-2^7 ~ 2^7-1

short

2

16

-2^15 ~2^15-1

int

4

32

-2^31 ~ 2^31-1

long

8

64

-2^63 ~ 2^63-1

char

2字节

16位

0~65535

float

4字节

32位

±3.4E+38

double

8字节

64位

±1.7E+308

boolean

4字节

32位

true\false

从上表中我们可以看到,整型的最大取值范围是-2^63 ~ 2^63-1,浮点型的最大取值范围是±1.7E+308。但是不管这个范围有多大,有些小伙伴就想杠一下,如果我就要存一个比Integer或Long更大的数字,怎么办?

针对这种大整数的需求,我们可以使用BigInteger,它的数字范围比 Integer类型的数字范围要大得多,而且BigInteger支持任意精度的整数。也就是说在运算中,BigInteger类型可以准确地表示任何大小的整数值。BigInteger和Integer、Long一样都是Number的子类,属于不可变类。它自身带有一些可以进行运算的方法,包括基本的加、减、乘、除操作,还有很多较为高级的操作,像求绝对值、相反数、最大公约数及判断是否为质数等,所以BigInteger用起来是比较方便的。

2. 使用方法

2.1 常用API方法

如果我们要使用BigInteger类,首先要创建一个BigInteger对象。BigInteger类提供了多个构造方法,其中最直接的一个是以字符串作为参数的构造方法,即BigInteger(String val)。在创建BigInteger对象之后,我们就可以调用BigInteger类提供的方法,进行各种数学运算了,这些常用的API方法如下:

方法名称

说明

add(BigInteger val)

做加法运算

subtract(BigInteger val)

做减法运算

multiply(BigInteger val)

做乘法运算

divide(BigInteger val)

做除法运算

remainder(BigInteger val)

做取余数运算

divideAndRemainder(BigInteger val)

做除法运算,返回数组的第一个值为商,第二个值为余数

pow(int exponent)

做参数的 exponent 次方运算

negate()

取相反数

shiftLeft(int n)

将数字左移 n 位,如果 n 为负数,则做右移操作

shiftRight(int n)

将数字右移 n 位,如果 n 为负数,则做左移操作

and(BigInteger val)

做与运算

or(BigInteger val)

做或运算

compareTo(BigInteger val)

做数字的比较运算

equals(Object obj)

当参数 obj 是 Biglnteger 类型的数字并且数值相等时返回 true, 其他返回 false

min(BigInteger val)

返回较小的数值

max(BigInteger val)

返回较大的数值

2.2 基本案例

我们先来通过一个案例,来验证一下BigInteger中的数字到底有多大。

public static void main(String[] args) {
	//创建一个BigInteger对象
	BigInteger bi = new BigInteger("1234567890");
	//计算1234567890的15次方,
	//结果=23589821655914838120947036369147203948318169938519404175968425823418008249115809912616071588527110255905622789563711716349000000000000000
	System.out.println(bi.pow(15)); 	
}

我们会发现,BigInteger可以表示一个非常大的数字,比Integer、Long的范围都要大。

2.3 类型转换

壹哥在上面说过,BigInteger其实是Number的子类,我们知道,Number中定义了几个负责类型转换的方法,比如:

  • 转换为bytebyteValue()
  • 转换为shortshortValue()
  • 转换为intintValue()
  • 转换为longlongValue()
  • 转换为floatfloatValue()
  • 转换为doubledoubleValue()

我们利用上述几个方法,就可以把BigInteger转换成基本类型。但是大家要注意,如果BigInteger表示的范围超过了基本类型的范围,在转换时会丢失高位信息,也就是说,结果不一定准确。所以如果我们需要准确地转换成基本类型,可以使用intValueExact()、longValueExact()这样的方法。不过这种方法在转换时如果超出了基本类型的范围,会直接抛出ArithmeticException异常。我们来验证一下吧。

public static void main(String[] args) {
	//BigInteger转基本类型
	BigInteger bi02 = new BigInteger("123456789000");
	//123456789000
	System.out.println("转为int类型="+bi02.intValue()); 
	System.out.println("转为float类型="+bi02.floatValue()); 
	System.out.println("转为long类型="+bi02.longValue()); 

	//将123456789000乘以123456789000,然后将结果转为long类型
	//java.lang.ArithmeticException: BigInteger out of long range
	System.out.println("得到精确结果="+bi02.multiply(bi02).longValueExact()); 
}

但是如果BigInteger的值超过了float的最大范围(3.4x1038),结果并不会出现ArithmeticException异常,而是会出现Infinity,如下所示:

//计算999999的99次方,并得到该结果的float值
BigInteger bi03 = new BigInteger("999999").pow(99);
float f = bi03.floatValue();
System.out.println("结果="+f);

2.4 其他用法

接下来我们再来看看其他的API方法都有哪些作用。

import java.math.BigInteger;
import java.util.Scanner;

/**
 * @author 一一哥Sun 
 */
public class Demo10 {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
        System.out.println("请输入一个整数:");
        // 保存用户输入的数字
        int num = scanner.nextInt();
        
        // 使用输入的数字创建BigInteger对象
        BigInteger bi = new BigInteger(num + "");
        // 计算大数字加上99的结果
        System.out.println("加法的结果:" + bi.add(new BigInteger("99")));
        // 计算大数字减去25的结果
        System.out.println("减法的结果:" + bi.subtract(new BigInteger("25")));
        // 计算大数字乘以3的结果
        System.out.println("乘法的结果:" + bi.multiply(new BigInteger("3")));
        // 计算大数字除以2的结果
        System.out.println("除法的结果:" + bi.divide(new BigInteger("2")));
        // 计算大数字除以3的商
        System.out.println("取商的结果:" + bi.divideAndRemainder(new BigInteger("3"))[0]);
        // 计算大数字除以3的余数
        System.out.println("取余的结果:" + bi.divideAndRemainder(new BigInteger("3"))[1]);
        // 计算大数字的4次方
        System.out.println("4次方的结果:" + bi.pow(4));
        // 计算大数字的相反数
        System.out.println("取反的结果:" + bi.negate());
	}

}

在上述案例中,我们将用户输入的数字作为 BigInteger 对象的参数,然后调用该对象的各种方法,实现了加、减、乘、除等运算,并输出了最终的结果。

二. BigDecimal类

1. 简介

虽然都是用于大数字运算的类,但BigDecimal加入了小数的概念,所以是可以操作小数的。而float 和 double类型,只能用来进行科学计算或工程计算,并不适用于精度要求较高的商业计算(如货币计算),所以要用到支持任何精度的BigDecimal类。该类中提供了一系列对应的方法,可以用来做超大浮点数的运算,像加、减、乘和除等。在所有运算中,除法运算是最复杂的,因为存在除不尽的情况,需要我们考虑末位小数的处理方式。

2. 使用方法

2.1 常用构造方法

以下是BigDecimal类的常用构造方法:

  • BigDecimal(double val):实例化对象时可以将双精度型转换为BigDecimal类型;
  • BigDecimal(String val):实例化对象时可以将字符串形式转换为BigDecimal类型。

2.2 常用API方法

除了构造方法之外,BigDecimal还提供了一些常用的API方法供我们进行数学运算。这些方法与BigInteger的方法类型,很多方法名称和用法也都与之一致,所以这里壹哥就不再一一列出了,接下来我就直接通过一个案例给大家演示这些方法如何使用。

import java.math.BigDecimal;

/**
 * @author 一一哥Sun V我领资料:syc_2312119590 各平台都有壹哥的同名博客哦
 */
public class Demo11 {

	public static void main(String[] args) {
		BigDecimal bd = new BigDecimal("1000.05800");
		// 计算大数字加上99的结果
        System.out.println("加法的结果:" + bd.add(new BigDecimal("99")));
        // 计算大数字减去25的结果
        System.out.println("减法的结果:" + bd.subtract(new BigDecimal("25")));
        // 计算大数字乘以1000的结果
        System.out.println("乘法的结果:" + bd.multiply(new BigDecimal(1000)));
		
		//获取小数的位数,5
		System.out.println(bd.scale()); 
		
		//去掉BigDecimal末尾的0,返回一个与原有BigDecimal相等的新对象
		BigDecimal bd2 = bd.stripTrailingZeros();
		System.out.println(bd2.scale()); 
	}

}

在上述代码中,stripTrailingZeros()方法用于去掉BigDecimal末尾的0,并返回一个与原有BigDecimal相等的新对象。而scale()方法用于获取一个数字后面0的个数,如果返回的是负数,比如-2,则表示该数是一个整数,且末尾有2个0。

2.3 divide()除法

BigDecimal进行加、减、乘时,数字的精度不会丢失,但是进行除法运算时,有可能会出现无法除尽的情况,此时必须指定精度以及如何进行截断。BigDecimal给我们提供了divide()和divideAndRemainder()两个方法可以进行除法运算。

其中,divide()方法有3个参数分别表示除数、商的小数点后的位数和近似值的处理模式,下表是壹哥给大家列出的roundingMode参数支持的处理模式。

模式名称

说明

BigDecimal.ROUND_UP

商的最后一位,如果大于 0,则向前进位,正负数都如此。

BigDecimal.ROUND_DOWN

商的最后一位无论是什么数字都省略

BigDecimal.ROUND_CEILING

商如果是正数,按照 ROUND_UP 模式处理;如果是负数,按照 ROUND_DOWN模式处理

BigDecimal.ROUND_FLOOR

与 ROUND_CELING 模式相反,商如果是正数,按照 ROUND_DOWN 模式处理;如果是负数,按照 ROUND_UP 模式处理

BigDecimal.ROUND_HALF_ DOWN

对商进行五舍六入操作。如果商最后一位小于等于 5,则做舍弃操作,否则对最后一位进行进位操作

BigDecimal.ROUND_HALF_UP

对商进行四舍五入操作。如果商最后一位小于 5,则做舍弃操作,否则对最后一位进行进位操作

BigDecimal.ROUND_HALF_EVEN

如果商的倒数第二位是奇数,则按照 ROUND_HALF_UP 处理;如果是偶数,则按照 ROUND_HALF_DOWN 处理

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * @author 一一哥Sun
 */
public class Demo12 {

	public static void main(String[] args) {
		BigDecimal d1 = new BigDecimal("123.456");
		BigDecimal d2 = new BigDecimal("123.456789");
		
		// 会产生ArithmeticException异常,因为除不尽,可以设置RoundingMode,按照指定的方法进行四舍五入或者直接截断:
		//BigDecimal d3 = d1.divide(d2); 
		
		// 保留10位小数并四舍五入
		BigDecimal d4 = d1.divide(d2, 10, RoundingMode.HALF_UP); 
		System.out.println("d4="+d4);
		//按指定的位数直接截断,0.xxxx
		BigDecimal d5 = d1.divide(d2, 4, RoundingMode.DOWN); 
		System.out.println("d5="+d5);
	}
}

2.4 divideAndRemainder()除法

而divideAndRemainder()方法,会返回一个数组,内部包含两个BigDecimal,分别是商和余数,其中商总是整数,余数不会大于除数,所以我们可以利用这个方法来判断两个BigDecimal是否是整数倍数。

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * @author 一一哥Sun 
 */
public class Demo12 {

	public static void main(String[] args) {
		//divideAndRemainder方法,返回一个数组,该数组内部包含了两个BigDecimal,分别是商和余数,其中商总是整数,余数不会大于除数。
		//我们可以利用这个特性来判断两个BigDecimal是否是整数倍数。
		BigDecimal n = new BigDecimal("123.456");
        BigDecimal m = new BigDecimal("0.123");
        BigDecimal[] dr = n.divideAndRemainder(m);
        System.out.println(dr[0]); // 1003
        System.out.println(dr[1]); // 0.087
        
        if (dr[1].signum() == 0) {
            // n是m的整数倍
        	System.out.println("n是m的整数倍"); 
        }else {
        	System.out.println("n不是m的整数倍"); 
        }
	}
}

3. 比较两个BigDecimal

如果我们想比较两个BigDecimal的值是否相等,需要特别注意,请不要使用equals()方法,因为使用该方式进行比较时,不但要求两个BigDecimal的值相等,还要求它们的scale()结果也相等。所以一般是建议使用compareTo()方法来比较,它会根据两个值的大小分别返回负数、正数和0,分别表示小于、大于和等于。如下所示:

import java.math.BigDecimal;

/**
 * @author 一一哥Sun
 */
public class Demo13 {

	public static void main(String[] args) {
		BigDecimal d1 = new BigDecimal("123.456");
		BigDecimal d2 = new BigDecimal("123.456000");
		// false,因为scale不同
		System.out.println("d1==d2? "+d1.equals(d2)); 
		// true,因为d2去除尾部0后scale变为2
		System.out.println("d1==d2? "+d1.equals(d2.stripTrailingZeros())); 
		 //结果=0,负数表示小于,正数表示大于,0表示等于
		System.out.println("d1==d2? "+d1.compareTo(d2));
	}

}

之所以需要使用compareTo()方法来比较两个BigDecimal的值才准确,这是因为一个BigDecimal实际上由一个BigInteger和一个scale组合而成的,其中BigInteger表示一个完整的整数,scale表示小数位数。如下图所示:

compareTo()方法内部会对小数位数进行判断,所以更准确,如下图:

4. 配套视频

与本节内容配套的视频链接如下:

External Player - 哔哩哔哩嵌入式外链播放器

-----------------------------------------------正片已结束,来根事后烟---------------------------------------------

三. 结语

至此,壹哥就把BigInteger、BigDecimal等大数字类介绍完毕了,最后给大家总结一下今天的重点内容:

  • BigInteger用于表示任意大小的整数;
  • BigInteger是不变类,并且继承自Number
  • BigInteger转换成基本类型时可使用longValueExact()等方法保证结果准确;
  • BigDecimal用于表示精确的小数,常用于财务计算;
  • 比较BigDecimal的值是否相等,必须使用compareTo()而不能使用equals()。

如果你独自学习觉得有很多困难,可以加入壹哥的学习互助群,大家一起交流学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1049763.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

不同材质地下管线的地质雷达响应特征分析

不同材质地下管线的地质雷达响应特征分析 前言 建立了不同材质地下管线(铸铁管线(PEC)、混凝土管线、PVC/PE管线)的二维模型,进行二维地质雷达正演模拟,分析不同材质管线的地质雷达响应特征。 文章目录 …

[chrome devtools]Sources面板

Source面板左侧部分内容: 下面解释每一项: Page:显示当前页面所有已加载的资源Filesystem:将本地代码拖进来,作为一个workspace,可以直接在这里面编辑代码,然后页面就可以直接看到效果&#xf…

【计算机网络】详解TCP协议(上) TCP协议头结构 | ACK确认应答 | 超时重传机制

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 更多计算机网络知识专栏&#xff1a;计算机网络&#x1f525; 给大家跳段…

深入理解服务发现:从基础到实践

随着微服务架构的广泛应用&#xff0c;服务发现已经成为了一个不可或缺的组成部分。服务发现是微服务架构中的一个关键问题&#xff0c;它涉及到如何管理和协调在一个分布式系统中的大量服务。本文将深入探讨服务发现的基本概念、工作原理和实践应用。我们将首先介绍服务发现的…

怎么使用 Go 语言操作 Apache Doris

Apache Doris 是一个基于 MPP 架构的高性能、实时的分析型数据库&#xff0c;以极速易用的特点被人们所熟知&#xff0c;仅需亚秒级响应时间即可返回海量数据下的查询结果&#xff0c;不仅可以支持高并发的点查询场景&#xff0c;也能支持高吞吐的复杂分析场景。基于此&#xf…

为什么 Lettuce 会带来更长的故障时间?

作者&#xff1a;杨博东&#xff08;凡澈&#xff09; 本文详述了阿里云数据库 Tair/Redis 将使用长连接客户端在非预期故障宕机切换场景下的恢复时间从最初的 900s 降到 120s 再到 30s的优化过程&#xff0c;涉及产品优化&#xff0c;开源产品问题修复等诸多方面。 一、背景 …

【数据结构】排序算法(一)—>插入排序、希尔排序、选择排序、堆排序

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.直接插入排序 2.希尔排序 3.直接选择排…

力扣:112. 路径总和(Python3)

题目&#xff1a; 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 叶子节点…

用css画一个半圆弧(以小程序为例)

一、html结构 圆弧的html结构是 两个块级元素嵌套。 <View classNamewrap><View className"inner">{/* 图标下的内容 */}</View></View>二、css样式&#xff1a;原理是两个半圆叠在一起&#xff0c;就是一个半圆弧。那么&#xff0c;如何画一…

【小白专属03】SpringBoot实现增删改查

目录 前言 一、新建Controller层 二、使用PostMan测试接口 前言 上节回顾 上一节我们SpringBoot集成了MybatisPlus。MybatisPlus是一个Mybatis的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 本节介绍 这一节&#x…

基于微信小程序的明星应援小程序设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

DirectX12_Windows_GameDevelop_0:启程之旅

前言 今天是2023年9月28日&#xff0c;明天就是中秋节了&#xff0c;先祝福大家中秋快乐&#xff01;时光飞逝&#xff0c;岁月如梭&#xff0c;大学四年一晃而逝&#xff0c;眨眼间我们即将毕业。毕业不是意味着要面对社会的险恶&#xff0c;也不是意味着要当打工社畜&#x…

cesium在vue中引入报错解决;cesium在vue中初始化地球

第一步&#xff1a; npm install cesium 第二步&#xff1a; 找到node_modules/cesium/Build/Cesium 文件夹&#xff0c;把这个 Cesium 文件夹复制一份到项目的 public 文件夹下 第三步&#xff1a; 在public文件夹下的index.html 文件中&#xff0c;head 标签里面&#…

51单片机实训项目之产品数量计数器

/********************************************************************************* * 【实验平台】&#xff1a; QX-MCS51 单片机开发板 * 【外部晶振】&#xff1a; 11.0592mhz * 【主控芯片】&#xff1a; STC89C52 * 【编译环境】&#xff1a; Keil μVisio3 * 【程序…

BiMPM实战文本匹配【上】

引言 今天来实现BiMPM模型进行文本匹配&#xff0c;数据集采用的是中文文本匹配数据集。内容较长&#xff0c;分为上下两部分。 数据准备 数据准备这里和之前的模型有些区别&#xff0c;主要是因为它同时有字符词表和单词词表。 from collections import defaultdict from …

3 OpenCV两张图片实现稀疏点云的生成

前文&#xff1a; 1 基于SIFT图像特征识别的匹配方法比较与实现 2 OpenCV实现的F矩阵RANSAC原理与实践 1 E矩阵 1.1 由F到E E K T ∗ F ∗ K E K^T * F * K EKT∗F∗K E 矩阵可以直接通过之前算好的 F 矩阵与相机内参 K 矩阵获得 Mat E K.t() * F * K;相机内参获得的方式…

spring6-IOC容器

IOC容器 1、IoC容器1.1、控制反转&#xff08;IoC&#xff09;1.2、依赖注入1.3、IoC容器在Spring的实现 2、基于XML管理Bean2.1、搭建子模块spring6-ioc-xml2.2、实验一&#xff1a;获取bean①方式一&#xff1a;根据id获取②方式二&#xff1a;根据类型获取③方式三&#xff…

Zilliz@阿里云:大模型时代下Milvus Cloud向量数据库处理非结构化数据的最佳实践

大模型时代下的数据存储与分析该如何处理?有没有已经落地的应用实践? 为探讨这些问题,近日,阿里云联合 Zilliz 和 Doris 举办了一场以《大模型时代下的数据存储与分析》为主题的技术沙龙,其中,阿里云对象存储 OSS 上拥有海量的非结构化数据,Milvus(Zilliz)作为全球最有…

华为摄像头智能安防监控解决方案

云时代来袭&#xff0c;数字化正在从园区办公延伸到生产和运营的方方面面&#xff0c;智慧校园&#xff0c;柔性制造&#xff0c;掌上金融和电子政务等&#xff0c;面对各种各样的新兴业态的涌现&#xff0c;企业需要构建一张无所不联、随心体验、业务永续的全无线网络&#xf…

多线程锁-线程锁知识概述、乐观锁和悲观锁

3. 说说Java"锁"事 3.1 从轻松的乐观锁和悲观锁开讲 悲观锁&#xff1a; 认为自己在使用数据的时候一定有别的线程来修改数据&#xff0c;因此在获取数据的时候会先加 锁&#xff0c;确保数据不会被别的线程修改&#xff0c;synchronized和Lock的实现类都是悲观锁…