广告
返回顶部
首页 > 资讯 > 前端开发 > html >BigDecimal遇到的坑有哪些
  • 236
分享到

BigDecimal遇到的坑有哪些

2024-04-02 19:04:59 236人浏览 独家记忆
摘要

这篇文章主要介绍“BigDecimal遇到的坑有哪些”,在日常操作中,相信很多人在BigDecimal遇到的坑有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”BigDec

这篇文章主要介绍“BigDecimal遇到的坑有哪些”,在日常操作中,相信很多人在BigDecimal遇到的坑有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”BigDecimal遇到的坑有哪些”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

避免用Double来进行运算

使用Double来计算,我们以为的算术运算和计算机计算的并不完全一直,这是因为计算机是以二进制存储数值的,我们输入的十进制数值都会转换成二进制进行计算,十进制转二进制再转换成十进制就不是原来那个十进制了,再也不是曾经那个少年了。举个例子:十进制的0.1转换成二进制是0.0  0011 0011  0011...(无数个0011),再转换成十进制就是0.1000000000000000055511151231,看到了吧,没有骗你的。

计算机无法精确地表达浮点数,这是不可避免的,这是为什么浮点数计算后精度损失的原因。

System.out.println(0.1+0.2); System.out.println(1.0-0.8); System.out.println(4.015*100); System.out.println(123.3/100);

BigDecimal遇到的坑有哪些

通过简单的例子,我们发现精度损失并不是很大,但是这并不代表我们可以使用,特别是电商类系统中,每天少说几百万的单量,每笔订单哪怕少计算一分钱,算下来也是一笔不小的金额,所以说,这不是个小事情,然后很多人就说,金额计算啊,你用BigDecimal啊,对的,这个没毛病,但是用了BigDecimal就完事大吉了吗?当问出这句话的时候,就说明这其中必有蹊跷。

BigDecimal你遇见过哪些坑?

还是通过一个简单的例子,计算上边例子中的运算,来看一下结果:

System.out.println(new BigDecimal(0.1).add(new BigDecimal(0.2))); System.out.println(new BigDecimal(1.0).subtract(new BigDecimal(0.8))); System.out.println(new BigDecimal(4.015).multiply(new BigDecimal(100))); System.out.println(new BigDecimal(123.3).divide(new BigDecimal(100)));

BigDecimal遇到的坑有哪些

我们发现使用了BigDecimal之后计算结果还是不精确,这里就要记住BigDecimal的第一个坑了:

BigDecimal来表示和计算浮点数的时候,要使用String的构造方法来初始化BigDecimal。

小的改进一下再来看看结果:

System.out.println(new BigDecimal("0.1").add(new BigDecimal("0.2"))); System.out.println(new BigDecimal("1.0").subtract(new BigDecimal("0.8"))); System.out.println(new BigDecimal("4.015").multiply(new BigDecimal("100"))); System.out.println(new BigDecimal("123.3").divide(new BigDecimal("100")));

BigDecimal遇到的坑有哪些

那么接下来一个问题,使用了BigDecimal就万事大吉了吗?并不是的!

接下来我们来看一下BigDecimal的源码,这里面有一个地方需要注意,先看图:

BigDecimal遇到的坑有哪些

注意看这两个属性,scale表示小数点右边几位,precision表示精度,就是我们常说的有效长度。

前边我们已经知道,BigDecimal必须传入字符串类型数值,那么如果我们现在是一个Double类型数值,该如何操作呢?通过一个简单的测试我们来看一下:

 private static void testScale() {      BigDecimal bigDecimal1 = new BigDecimal(Double.toString(100));      BigDecimal bigDecimal2 = new BigDecimal(String.valueOf(100d));      BigDecimal bigDecimal3 = BigDecimal.valueOf(100d);      BigDecimal bigDecimal4 = new BigDecimal("100");      BigDecimal bigDecimal5 = new BigDecimal(String.valueOf(100));       print(bigDecimal1);      print(bigDecimal2);      print(bigDecimal3);      print(bigDecimal4);      print(bigDecimal5);      }  private static void print(BigDecimal bigDecimal) {         System.out.println(String.fORMat("scale %s precision %s result %s", bigDecimal.scale(), bigDecimal.precision(), bigDecimal.multiply(new BigDecimal("1.001")))); }

run一下我们发现,以上前三种方式是将double转换成BigDecimal之后,得到的BigDecimal的scale都是1,precision都是4,后两种方式的toString方法得到的scale都是0,precision都是3,与1.001进行乘运算后,我们发现,scale是两个数的scale相加的结果。

BigDecimal遇到的坑有哪些

我们在处理浮点数的字符串的时候,应该显式的方式通过格式化表达式或者格式化工具来明确小数位数和舍入方式。

浮点数的舍入和格式化该如何选择?

我们首先来看看使用String.format的格式化舍入,会有什么结果,我们知道浮点数有double和float两种,下边我们就用这两种来举例子:

double num1 = 3.35; float num2 = 3.35f; System.out.println(String.format("%.1f", num1)); System.out.println(String.format("%.1f", num2));

BigDecimal遇到的坑有哪些

得到的结果似乎与我们的预期有出入,其实这个问题也很好解释,double和float的精度是不同的,double的3.35相当于3.350000000000000088817841970012523233890533447265625,而float的3.35相当于3.349999904632568359375,String.format才有的又是四舍五入的方式舍入,所以精度问题和舍入方式就导致了运算结果与我们预期不同。

Formatter类中默认使用的是HALF_UP的舍入方式,如果我们需要使用其他的舍入方式来格式化,可以手动设置。

到这里我们就知道通过String.format的方式来格式化这条路坑有点多,所以,「浮点数的字符串格式化还得要使用BigDecimal来进行」。

来,上代码,测试一下究竟是不是那么回事:

BigDecimal num1 = new BigDecimal("3.35"); //小数点后1位,向下舍入 BigDecimal num2 = num1.setScale(1, BigDecimal.ROUND_DOWN); System.out.println(num2); //小数点后1位,四舍五入 BigDecimal num3 = num1.setScale(1, BigDecimal.ROUND_HALF_UP); System.out.println(num3); 输入结果: 3.3 3.4

这次得到的结果与我们预期一致。

BigDecimal不能使用equals方法比较?

我们都知道,包装类的比较要使用equals,而不能使用==,那么这一条在Bigdecimal中也适用吗?数据说话,简单的一个测试来说明:

System.out.println(new BigDecimal("1").equals(new BigDecimal("1.0"))) 结果:false

按照我们的理解1和1.0是相等的,也应该是相等的,但是Bigdecimal的equals在比较中不只是比较了value,还比较了scale,我们前边说了scale是小数点后的位数,明显两个值的小数点后位数不一样,所以结果为false。

实际的使用中,我们常常是只希望比较两个BigDecimal的value,这里就要注意,要使用compareTo方法:

System.out.println(new BigDecimal("1").compareTo(new BigDecimal("1.0"))) 结果:true

到此,关于“BigDecimal遇到的坑有哪些”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: BigDecimal遇到的坑有哪些

本文链接: https://www.lsjlt.com/news/84182.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • BigDecimal遇到的坑有哪些
    这篇文章主要介绍“BigDecimal遇到的坑有哪些”,在日常操作中,相信很多人在BigDecimal遇到的坑有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”BigDec...
    99+
    2022-10-19
  • 使用recvfrom函数遇到的坑有哪些
    使用recvfrom函数时可能会遇到以下几个常见的问题:1. 阻塞问题:recvfrom函数默认是阻塞的,即当没有收到数据时,程序会...
    99+
    2023-08-24
    recvfrom
  • Android Studio升级到3.0后遇到的坑有哪些
    这篇文章主要介绍Android Studio升级到3.0后遇到的坑有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!第一坑、必须升级gradle到4.0以上相信这个大坑,一般使用as的人都会解决了,所以就不多说第二...
    99+
    2023-05-30
    android studio
  • vue resource post请求时遇到的坑有哪些
    这篇文章将为大家详细讲解有关vue resource post请求时遇到的坑有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。使用 post 请求// glo...
    99+
    2022-10-19
  • 使用try-catch-finally常遇到的坑有哪些
    本篇内容主要讲解“使用try-catch-finally常遇到的坑有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“使用try-catch-finally常遇到的坑有哪些”吧!坑1:final...
    99+
    2023-06-15
  • Oracle遇到的一些坑
    1、tnsping 实例名 报错:在服务器上修改tns监听配置文件,我的路径在 /home/oracle/app/oracle/product/11.2.0/dbhome_1/network/admin/t...
    99+
    2022-10-18
  • mysql中timestamp比较查询遇到的坑有哪些
    这篇文章主要介绍mysql中timestamp比较查询遇到的坑有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!timestamp比较查询遇到的坑要求mysql建表的时候update_time 为timestamp...
    99+
    2023-06-21
  • 微信JS-SDK选择图片遇到的坑有哪些
    这篇文章主要介绍了微信JS-SDK选择图片遇到的坑有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。有个需求要在微信企业号里面做开发,有个...
    99+
    2022-10-19
  • 微信小程序开发时遇到的坑有哪些
    这篇文章主要讲解了“微信小程序开发时遇到的坑有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“微信小程序开发时遇到的坑有哪些”吧!最近参与开发了公司的第一款小程序,开发体验基本类似于基于w...
    99+
    2023-06-13
  • mybatis if test判断BigDecimal遇到的坑及解决方法是什么
    这篇“mybatis if test判断BigDecimal遇到的坑及解决方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获...
    99+
    2023-07-05
  • Python分布式进程中会遇到的坑都有哪些呢
    Python分布式进程中会遇到的坑都有哪些呢,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。小惊大怪你是不是在用Python3或者在windows系统上编程最重要的是你对进程和线...
    99+
    2023-06-16
  • stm32+FreeRTOS遇到的坑
    问题 最近把项目移植进FreeRTOS时,发现开始任务都不能启动; 机器是stm32f407,使用的arm固件和FreeRTOS都是最新版本; 裸机运行没有问题,但是使用任务运行就运行不了; 排查 首先尝试了教程用的点灯代码,发现可以正常运...
    99+
    2023-08-30
    stm32 嵌入式硬件 单片机 FreeRTOS
  • 使用RxJava中遇到的一些”坑“
    前言大家越用RxJava,越觉得它好用,所以不知不觉地发现代码里到处都是RxJava的身影。然而,RxJava也不是银弹,其中仍然有很多问题需要解决。这里,我简单地总结一下自己遇到的一些“坑”,内容上可能会比较松散。一、考虑主线程的切换Rx...
    99+
    2023-05-31
    rxjava 使用 ava
  • 我从jdk1.8升级到jdk11所遇到的坑都有这些
    目录一、jdk11 移除了 Base64替代方案二、Maven 打包报错修改方案,更新maven打包插件三、Lombok 无法使用解决方案,升级lombok四、xmlelement ...
    99+
    2022-11-12
  • elasticsearch7.5安装遇到的坑
    没错,从零开始的elasticsearch搭建教程开始了!h"h ** 原文:https://www.cnblogs.com/heermayou/p/12670662.html 那么首先假设 你已经装好了一个CentOS系统 ,我...
    99+
    2017-03-23
    elasticsearch7.5安装遇到的坑
  • Spring中@RequestParam使用及遇到的一些坑
    目录加与不加的区别使用RequestParam遇到的一些坑(总结)总结加与不加的区别 @RequestMapping("/list1") public String test1(in...
    99+
    2022-11-13
  • springcloudoauth2feign遇到的坑及解决
    目录springcloudoauth2feign遇到的坑客户端模式基于springsecurityspringcloud微服务增加oauth2权限后feign调用报null一般是这样...
    99+
    2022-11-13
  • ubuntu安装mysql遇到的坑---
    最近学习大数据,涉及到hive的部分需要安装mysql,于是就在linux环境下尝试安装,对于我这个linux小白来说,中间遇到很多坑爹问题,在这里做一个记录。 我参考的mysql安装博客: https://www.cnblogs.com...
    99+
    2023-01-30
    ubuntu mysql
  • @ConfigurationProperties遇到的坑及解决
    想着偷懒,直接使用@ConfigurationProperties(prefix="xxx")读取配置文件,不使用@Value("${xxx}")去一个一个的注入。 遇到的坑: 创...
    99+
    2022-11-12
  • ubuntu安装pyspider遇到的坑
    apt-get install python python-dev python-distribute python-pip \libcurl4-openssl-dev libxml2-dev libxslt1-dev python-lxm...
    99+
    2023-01-31
    ubuntu pyspider
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作