Java 高精度计算 BigDecimal 和 BigInteger

2023-11-17

BigDecimal

在 Java 中,表示小数值一般使用 float 或者 double 类型,可以用于科学计算或者工程计算等。数学意义上的小数是连续的,但 float 和 double 只能表示其中的一些离散点,如果我们要表示的数值刚好无法用 float 或者 double 精确表示的话,那么它会找一个最近的值来近似表示。float 类型的有效精度为6到7位。double 类型的有效精度为16倍。

如下所示,float 和 double 类型的计算结果可能出乎我们的预料。

package com.chenpi;

/**
 * @author 陈皮
 * @version 1.0
 * @description
 * @date 2022/3/25
 */
public class ChenPi {

  public static void main(String[] args) {

    double d1 = 0.2;
    double d2 = 0.1;
    double d3 = d1 + d2;
    System.out.println(d3);

    float f1 = 0.1f;
    float f2 = 0.2f;
    float f3 = f1 * f2;
    System.out.println(f3);
  }
}

// 输出结果如下
0.30000000000000004
0.020000001

在商业计算,银行金融等领域,要求数字的精度非常高。推荐使用 BigDecimal 类,它能支持任何精度的定点数。

package com.chenpi;

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

/**
 * @author 陈皮
 * @version 1.0
 * @description
 * @date 2022/3/25
 */
public class ChenPi {

  public static void main(String[] args) {

    BigDecimal bigDecimal1 = new BigDecimal("0.1");
    BigDecimal bigDecimal2 = new BigDecimal("0.2");

    // 加法
    System.out.println(bigDecimal1.add(bigDecimal2));
    // 减法
    System.out.println(bigDecimal1.subtract(bigDecimal2));
    // 乘法
    System.out.println(bigDecimal1.multiply(bigDecimal2));
    // 除法,保留2位小数,向上取舍
    System.out.println(bigDecimal1.divide(bigDecimal2, 2, RoundingMode.HALF_UP));
    // 小数点往左移2位
    System.out.println(bigDecimal1.movePointLeft(2));
    // 小数点往右移1位
    System.out.println(bigDecimal1.movePointRight(1));
    // 转为double值
    System.out.println(bigDecimal1.doubleValue());
    // 2次方
    System.out.println(bigDecimal1.pow(2));

  }
}

注意,不要使用 double 参数的构造方法,因为传入的原因 double 值可能就不准确的,如下所示。

package com.chenpi;

import java.math.BigDecimal;

/**
 * @author 陈皮
 * @version 1.0
 * @description
 * @date 2022/3/25
 */
public class ChenPi {

  public static void main(String[] args) {
    BigDecimal bigDecimal1 = new BigDecimal(0.1);
    System.out.println(bigDecimal1);
  }
}

// 输出结果如下
0.1000000000000000055511151231257827021181583404541015625

在对两个 BigDecimal 对象进行比较时,不要使用 equals,推荐使用 compareTo。因为 equals 方法会是比较小数的位数,这样对于 0.1 和 0.10 就会返回 false。

package com.chenpi;

import java.math.BigDecimal;

/**
 * @author 陈皮
 * @version 1.0
 * @description
 * @date 2022/3/25
 */
public class ChenPi {

  public static void main(String[] args) {
    BigDecimal bigDecimal1 = new BigDecimal("21.1");
    BigDecimal bigDecimal2 = new BigDecimal("21.10");

    // 数值相等,但是小数位不相等,导致结果为false
    System.out.println("equals:" + bigDecimal1.equals(bigDecimal2));

    // 比较的推荐用法
    System.out.println("compareTo:" + bigDecimal1.compareTo(bigDecimal2));

    // 比较是否等于0的用法
    BigDecimal bigDecimal3 = new BigDecimal("0.0");
    if (BigDecimal.ZERO.compareTo(bigDecimal3) == 0) {
      System.out.println("bigDecimal3 等于0");
    }
  }
}

// 输出结果如下
equals:false
compareTo:0
bigDecimal3 等于0

BigInteger

在 Java 中,Integer 和 Long 的最大值和最小值范围如下所示。

package com.chenpi;

/**
 * @author 陈皮
 * @version 1.0
 * @description
 * @date 2022/3/25
 */
public class ChenPi {

  public static void main(String[] args) {

    int mini = Integer.MIN_VALUE;
    int maxi = Integer.MAX_VALUE;
    System.out.println(mini + " ~ " + maxi);
    System.out.println(Integer.toBinaryString(mini) + " ~ " + Integer.toBinaryString(maxi));

    long minl = Long.MAX_VALUE;
    long maxl = Long.MIN_VALUE;
    System.out.println(minl + " ~ " + maxl);
    System.out.println(Long.toBinaryString(minl) + " ~ " + Long.toBinaryString(maxl));
  }
}

// 输出结果如下
-2147483648 ~ 2147483647
10000000000000000000000000000000 ~ 1111111111111111111111111111111

9223372036854775807 ~ -9223372036854775808
111111111111111111111111111111111111111111111111111111111111111 ~ 1000000000000000000000000000000000000000000000000000000000000000

但如果我们想表示的数字超过这个范围的话,可以使用 BigInteger 类型,它可以表示更大范围的整数。

package com.chenpi;

import java.math.BigInteger;

/**
 * @author 陈皮
 * @version 1.0
 * @description
 * @date 2022/3/25
 */
public class ChenPi {

  public static void main(String[] args) {

    BigInteger bigInteger1 = new BigInteger("922337203685477580711");
    BigInteger bigInteger2 = new BigInteger("922337203685477580722");

    // 加
    System.out.println(bigInteger1.add(bigInteger2));
    // 减
    System.out.println(bigInteger1.subtract(bigInteger2));
    // 乘
    System.out.println(bigInteger1.multiply(bigInteger2));
    // 除
    System.out.println(bigInteger1.divide(bigInteger2));

  }
}

// 输出结果如下
1844674407370955161433
-11
850705917302346158504406205563945772653342
0

本次分享到此结束啦~~

如果觉得文章对你有帮助,点赞、收藏、关注、评论,您的支持就是我创作最大的动力!

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

Java 高精度计算 BigDecimal 和 BigInteger 的相关文章

随机推荐

  • 记一次Prometheus监控下的“内存飙升”事件

    问题描述 尝试定位问题 错误的表达式 重叠的时间序列 Prometheus的高可用机制 联邦集群 修改PromQL表达式 结语 本文将介绍一次在使用Prometheus过程中由于表达式错误引发的问题 以及解决过程 问题描述 项目上的API用
  • Json的float单精度浮点数类型支持Can't assign value '11.88' (type System.Double) to type System.Single

    今天遇到个问题Can t assign value 11 88 type System Double to type System Single litjson不支持单精度浮点数float 只用修改JsonMapper cs脚本就可以 一共
  • 机器学习之从基础数学深入剖析逻辑回归(案例理论相结合)

    逻辑回归 一 从回归问题到分类问题 回归基础请见上一篇文章 https blog csdn net sjjsaaaa article details 115967347 1 机器学习中的分类问题 事物的类别 正确的分类观是建立科学体系 训练
  • 数字系统的信息表示

    数字系统的信息表示 1 什么是信息 2 数字系统是如何表示一个连续值的信息 3 使用数字信号的优势 4 将模拟信号表示成数字信号形式过程 5 为什么数字系统要采用二进制 6 噪声容限 1 什么是信息 信息是对物质世界与人类社会中存在的各种各
  • 网络安全中的欺骗攻击与防御技术

    在Internet上计算机之间相互进行的交流建立在两个前提之下 认证 信任 认证是网络上的计算机用于相互间进行识别的一种鉴别过程 经过认证的过程 获准相互交流的计算机之间就会建立起相互信任的关系 信任和认证具有逆反关系 即如果计算机之间存在
  • 介值定理究竟在讲什么?

    介值定理 书本上的定义 翻译成人话就是 函数最原始的定义 我们初中就知道 一个函数最根本的性质就是 函数值 自变量值 一一对应 所以介值定理就是在反复说一件事 一个数如果属于值域 在定义域内 一定能够找到一个 自变量 与其对应 当然这个结论
  • Shell—关于source,bash如何执行

    通过对一个脚本问题的分析 发现了自己的一个知识误区 我想 有必要写篇博客总结一下 关于source source test sh 与 test sh 二者用法相同 是读取脚本test sh中的内容 依次在当前脚本中执行 且不会建立新的子sh
  • 【论文精读IEEE_2023_6】FlowFace++: Explicit Semantic Flow-supervised End-to-End Face Swapping

    论文精读CVPR 2023 6 FlowFace Explicit Semantic Flow supervised End to End Face Swapping 一 前言 Abstract I INTRODUCTION II RELA
  • matlab 三维激光雷达点云的路缘检测与跟踪

    目录 Introduction Download Lidar Data Set Preprocess Data Detect Road Shape Detect Road Curbs Track Curb Points Analyze Dr
  • 记录用ConstraintLayout实现控件view最大高度的过程

    背景 我项目里用到个popupWindow 内容是掉接口获取的list 长度不固定 就想着弄个最大高度 让他在内容过多的时候不会太长怼到屏幕底部 开整 看constraintLayout的文章说用android maxHeight 250d
  • how to activate XMind8 to pro version.

    From activate Xmind 8 in step 3 run setup sh in sudo command and use the following command to run XMind XMind Activate X
  • 立创开源

    一 项目说明 我们在使用单片机设计项目时经常需要用到ADC功能 但是众所周知 单片机是很脆弱的东西 一旦采样 分压后 的电压超过3 3v就会瞬间罢工 在烧毁4 5个单价不菲的单片机后我认为使用外部ADC很有必要 由此本项目诞生 二 原理图
  • 【解决】nltk.download()报错:errno54: connection reset by peer

    报错详情 import nltk gt gt gt nltk download nltk data Error loading
  • github不再支持账号密码解决方案

    今天在向github上传代码的时候 突然不能上传了 终端报错信息如下 remote Support for password authentication was removed on August 13 2021 Please use a
  • C语言中将变量的数值打印到.txt文件

    1 C语言中只需加入以下代码即可将变量的数值打印到 txt文件中 FILE fp fopen dayin txt a fprintf fp d n 变量名 fclose fp 2 若想每次运行C程序就覆盖掉上一次生成的 txt文件 则需要先
  • 深入PCI与PCIe之一:硬件篇

    PCI总线和设备树是X86硬件体系内很重要的组成部分 几乎所有的外围硬件都以这样或那样的形式连接到PCI设备树上 虽然Intel为了方便各种IP的接入而提出IOSF总线 但是其主体接口 primary interface 还依然是PCIe形
  • 人才盘点的主角是业务部门负责人还是HR?

    你的企业 是否存在以下问题 人才储备不足 关键岗位人员离职后 没有合适的马上接替 人才质量不高 企业战略变革转型期 不知谁可以引领和驱动变革 人才现状不清 新的业务 新的项目要开拓 不知合适的人才在哪里 人才分布不均 成熟业务部门人才扎堆
  • gin框架38--使用中间件

    gin框架38 使用中间件 介绍 案例 说明 介绍 本文主要介绍如何在gin框架中使用中间件 并通过案例加以说明 使用MyBenchLogger中间件来输出特有的日志 用AuthRequire中间件来实现基础认证 案例 package ma
  • Cost function

    cost function的形式 cost function的推导满足以下过程 1 认为error 满足某个分布 写出样本点xi的样本的error 2 认为样本点是相互独立的 推导出其对数似然函数 3 求偏导 是得导函数为0 分离常数部分
  • Java 高精度计算 BigDecimal 和 BigInteger

    BigDecimal 在 Java 中 表示小数值一般使用 float 或者 double 类型 可以用于科学计算或者工程计算等 数学意义上的小数是连续的 但 float 和 double 只能表示其中的一些离散点 如果我们要表示的数值刚好