当前位置: 首页 > news >正文

Java大数处理:BigInteger与BigDecimal

文章目录

  • Java大数处理:BigInteger与BigDecimal
    • 1. 引入:为什么需要大数?
      • 1.1 基本数据类型的局限
      • 1.2 解决方案:大数类
    • 2. BigInteger:超大整数
      • 2.1 创建BigInteger对象
      • 2.2 基本运算
      • 2.3 比较和判断
      • 2.4 其他常用方法
      • 2.5 实际应用:计算阶乘
    • 3. BigDecimal:高精度小数
      • 3.1 为什么需要BigDecimal?
      • 3.2 创建BigDecimal对象
      • 3.3 基本运算
      • 3.4 除法与舍入模式
      • 3.5 设置精度和比较
      • 3.6 stripTrailingZeros:去除末尾零
    • 4. BigInteger vs BigDecimal 对比
    • 5. 大数结构的底层原理(扩展)
      • 5.1 大数的存储方式
      • 5.2 基本运算原理
      • 5.3 为什么字符串构造更准确?
    • 6. 实际应用场景
      • 6.1 金额计算
      • 6.2 大数阶乘
      • 6.3 高精度开方/幂
    • 7. 易错点总结
    • 8. 综合总结

Java大数处理:BigInteger与BigDecimal

1. 引入:为什么需要大数?

1.1 基本数据类型的局限

在Java中,基本数据类型有固定的取值范围:

类型位数最大值
int32位约21亿(2^31-1)
long64位约9.22×1018(263-1)
double64位约1.8×10^308(但精度有限)
inta=2147483647;// int最大值intb=a+1;// 溢出,变成-2147483648longc=9223372036854775807L;// long最大值longd=c+1;// 溢出,变成-9223372036854775808

问题:如果需要计算天文数字(如100的阶乘、圆周率后1000位),基本类型完全不够用。

1.2 解决方案:大数类

Java提供了两个专门处理大数的类:

  • BigInteger:处理超大整数
  • BigDecimal:处理超高精度小数

它们可以表示任意大小的数字,只受内存限制。


2. BigInteger:超大整数

2.1 创建BigInteger对象

importjava.math.BigInteger;// 方式1:通过字符串(推荐)BigIntegernum1=newBigInteger("12345678901234567890");// 方式2:通过long(不推荐,因为long本身可能溢出)BigIntegernum2=BigInteger.valueOf(100);// 方式3:常用常量BigIntegerzero=BigInteger.ZERO;BigIntegerone=BigInteger.ONE;BigIntegerten=BigInteger.TEN;

注意:BigInteger是不可变对象,所有操作都会返回新的BigInteger。

2.2 基本运算

BigIntegera=newBigInteger("100");BigIntegerb=newBigInteger("20");// 加减乘除BigIntegersum=a.add(b);// 加法:120BigIntegerdiff=a.subtract(b);// 减法:80BigIntegerproduct=a.multiply(b);// 乘法:2000BigIntegerquotient=a.divide(b);// 除法:5BigIntegerremainder=a.remainder(b);// 余数:0// 混合运算:a + b * 10 - 5BigIntegerresult=a.add(b.multiply(BigInteger.TEN)).subtract(BigInteger.valueOf(5));

2.3 比较和判断

BigIntegera=newBigInteger("100");BigIntegerb=newBigInteger("200");// 比较大小:返回-1(小于), 0(等于), 1(大于)intcmp=a.compareTo(b);// -1// 判断是否相等booleanisEqual=a.equals(b);// false// 判断是否为0booleanisZero=a.equals(BigInteger.ZERO);// 取最大值/最小值BigIntegermax=a.max(b);// 200BigIntegermin=a.min(b);// 100

2.4 其他常用方法

BigIntegernum=newBigInteger("12345");// 绝对值BigIntegerabs=num.abs();// 幂运算BigIntegerpower=BigInteger.valueOf(2).pow(10);// 2^10 = 1024// 取相反数BigIntegerneg=num.negate();// -12345// 转为基本类型(可能溢出)intintVal=num.intValue();// 12345,超出范围会截断longlongVal=num.longValue();// 12345Stringstr=num.toString();// "12345"// 检查是否能转为int/long而不溢出booleancanConvert=num.bitLength()<32;// 判断是否在int范围内

2.5 实际应用:计算阶乘

publicstaticBigIntegerfactorial(intn){BigIntegerresult=BigInteger.ONE;for(inti=2;i<=n;i++){result=result.multiply(BigInteger.valueOf(i));}returnresult;}// 计算100的阶乘BigIntegerfact=factorial(100);System.out.println(fact);// 输出一个巨大的数(有158位)

3. BigDecimal:高精度小数

3.1 为什么需要BigDecimal?

看一个double的精度问题:

doublea=0.1;doubleb=0.2;System.out.println(a+b);// 0.30000000000000004 ????

因为二进制无法精确表示0.1,所以double运算会有精度损失。BigDecimal用来解决这个问题

3.2 创建BigDecimal对象

importjava.math.BigDecimal;// 方式1:用字符串(推荐,精度准确)BigDecimalnum1=newBigDecimal("0.1");BigDecimalnum2=newBigDecimal("0.2");// 方式2:用double(不推荐,已经有精度损失)BigDecimalnum3=newBigDecimal(0.1);// 得到的是0.100000000000000005...// 方式3:用valueOf(内部用字符串,推荐)BigDecimalnum4=BigDecimal.valueOf(0.1);// 常用常量BigDecimalzero=BigDecimal.ZERO;BigDecimalone=BigDecimal.ONE;BigDecimalten=BigDecimal.TEN;

重点:优先使用new BigDecimal("字符串")BigDecimal.valueOf(),不要用new BigDecimal(double)

3.3 基本运算

BigDecimala=newBigDecimal("10.5");BigDecimalb=newBigDecimal("3.2");BigDecimalsum=a.add(b);// 加法:13.7BigDecimaldiff=a.subtract(b);// 减法:7.3BigDecimalproduct=a.multiply(b);// 乘法:33.60// 除法需要指定舍入模式BigDecimalquotient=a.divide(b,2,RoundingMode.HALF_UP);// 3.28,保留2位,四舍五入

3.4 除法与舍入模式

除法最容易出问题,因为可能产生无限小数:

BigDecimala=newBigDecimal("10");BigDecimalb=newBigDecimal("3");// 不指定精度会抛异常(ArithmeticException)// BigDecimal c = a.divide(b); // 无限小数,报错// 正确用法:指定小数位数和舍入模式BigDecimalc=a.divide(b,2,RoundingMode.HALF_UP);// 3.33

常用舍入模式

舍入模式说明例子(保留2位)
HALF_UP四舍五入3.135 → 3.14
HALF_DOWN五舍六入3.135 → 3.13
CEILING向上取整3.131 → 3.14
FLOOR向下取整3.139 → 3.13
UP远离零3.131 → 3.14,-3.131 → -3.14
DOWN接近零3.139 → 3.13

3.5 设置精度和比较

BigDecimala=newBigDecimal("10.555");BigDecimalb=newBigDecimal("10.5550");// 设置小数位数BigDecimalrounded=a.setScale(2,RoundingMode.HALF_UP);// 10.56// 比较大小(使用compareTo,不要用equals)intcmp=a.compareTo(b);// 0,因为值相同(10.555 == 10.5550)booleanisEqual=a.equals(b);// false!因为位数不同// 正确比较if(a.compareTo(b)==0){System.out.println("值相等");}

重点equals会比较小数位数,compareTo只比较数值。比较值是否相等时用compareTo

3.6 stripTrailingZeros:去除末尾零

BigDecimalnum=newBigDecimal("10.5000");BigDecimalstripped=num.stripTrailingZeros();// 10.5System.out.println(stripped.toPlainString());// "10.5"(不用科学计数法)

4. BigInteger vs BigDecimal 对比

维度BigIntegerBigDecimal
用途超大整数高精度小数
适用场景阶乘、大数运算、密码学金额计算、科学计算
小数点没有
除法默认整除(直接除)需要指定精度和舍入
常见异常ArithmeticException(无限小数)
性能稍快稍慢

5. 大数结构的底层原理(扩展)

5.1 大数的存储方式

BigInteger内部使用int[]来存储数字:

// 简化版的大数结构publicclassMyBigInteger{privateint[]mag;// 存储数字的绝对值privateintsignum;// 符号:-1(负), 0(零), 1(正)}

例如,数字1234567890会被拆分成多个int存储,类似把数字按进制拆分

5.2 基本运算原理

加法:从低位到高位逐位相加,处理进位

1234 + 5678 = 6912 (进位处理)

乘法:类似手算竖式乘法,复杂度O(n²)

5.3 为什么字符串构造更准确?

// double构造:0.1在二进制中是无限循环小数,传入时已经失真newBigDecimal(0.1)0.100000000000000005551115123125...// 字符串构造:直接按十进制解析,完全精确newBigDecimal("0.1")0.1

6. 实际应用场景

6.1 金额计算

// 错误:用double算钱doubleprice=19.99;doubletax=price*0.08;// 1.5992000000000002,精度丢失// 正确:用BigDecimalBigDecimalprice=newBigDecimal("19.99");BigDecimaltax=price.multiply(newBigDecimal("0.08"));BigDecimaltotal=price.add(tax);total=total.setScale(2,RoundingMode.HALF_UP);// 保留两位小数

6.2 大数阶乘

publicstaticBigIntegerfactorial(intn){BigIntegerresult=BigInteger.ONE;for(inti=2;i<=n;i++){result=result.multiply(BigInteger.valueOf(i));}returnresult;}// 计算50!,结果有65位

6.3 高精度开方/幂

// 计算2的1000次方BigIntegerpower=BigInteger.valueOf(2).pow(1000);// 高精度开方BigDecimalnum=newBigDecimal("2");BigDecimalsqrt=sqrt(num,50);// 开方,保留50位小数(需要自己实现)

7. 易错点总结

易错点错误写法正确写法
用double构造BigDecimalnew BigDecimal(0.1)new BigDecimal("0.1")
除法不指定精度a.divide(b)a.divide(b, 2, RoundingMode.HALF_UP)
用equals比较BigDecimala.equals(b)a.compareTo(b) == 0
忘记BigDecimal不可变a.add(b)认为a变了a = a.add(b)
用valueOf传入浮点数BigDecimal.valueOf(0.1)用字符串构造更好
比较BigInteger用==a == ba.equals(b)

8. 综合总结

场景推荐类型原因
精确金额计算BigDecimal避免浮点精度问题
超大整数运算BigInteger任意大小整数
普通整数运算int/long性能好
普通浮点运算double性能好,不要求精度
科学计算double/BigDecimal看精度要求

一句话总结

要精确用BigDecimal,要超大用BigInteger,普通场景用基本类型。

http://www.jsqmd.com/news/707422/

相关文章:

  • 从“词向量相亲”到“上下文理解”:用生活例子拆解Self-Attention为什么让NLP开窍了
  • SAP MIGO过账时,这3个BAdI和User Exit千万别乱用(附MB_DOCUMENT_BADI实战避坑指南)
  • 今天力扣周赛 , 就做出来了三道题 . 我真的也是废了 ... (简短版)
  • 2026市面上比较好的专利律所口碑推荐及选择参考 - 品牌排行榜
  • Voxtral-4B-TTS-2603快速入门:Web工具页UI功能分区与交互流程图解
  • 2026国内符合马来西亚标准防火卷帘门厂家推荐排行 - 品牌排行榜
  • UI-TARS-desktop轻量级体验:低配电脑也能流畅运行的AI桌面应用
  • 油藏模拟中线性求解器的优化与Arm架构实践
  • 2026市场耐用的国标pvdf管优质厂家推荐 - 品牌排行榜
  • 深度学习梯度爆炸问题与梯度裁剪技术详解
  • Oracle11g服务端安装包
  • 保姆级教程:在Android Automotive 14模拟器上配置多屏(仪表+中控+副驾)并修改分辨率
  • 个人学习笔记12
  • 快速入门Face3D.ai Pro:零代码生成专业级3D人脸模型
  • 基于Crypto APIs构建MCP服务器:AI与区块链交互的共享工具库实践
  • 2026年市面上符合摩洛哥标准防火卷帘门厂家排行 - 品牌排行榜
  • Pinpoint C Agent 实战指南:PHP/Python 微服务链路追踪部署与调优
  • Phi-3-mini-4k-instruct-gguf快速上手:Git版本控制下的模型项目协作管理
  • Phi-mini-MoE-instructGPU利用率提升:通过batch size与kv cache优化
  • AgenticHub:macOS原生AI工具资源管理器,高效管理MCP服务器与Agent技能
  • 别死记硬背!用“白兔的分身术”等5道蓝桥杯真题,带你掌握C/C++算法题的降维打击思维
  • 机器学习中五大核心离散概率分布详解与应用
  • VideoDownloadHelper视频下载助手:3分钟快速上手终极指南
  • AI 技术日报 - 2026-04-27
  • DeepWideResearch:AI研究中深度与广度双螺旋协作模式解析
  • 深入理解 async/await的原理
  • 构建个人神经科学知识库:基于Git与Markdown的“第二大脑”实践
  • 2026年收藏指南:三招让论文AI率直接砍半,毕业查重稳过,实测有效! - 降AI实验室
  • AI像素画创作:pixel-agents智能体框架原理与实践指南
  • aLEAKator混合域模拟技术:硬件安全验证新突破