double转bigDecimal精度问题

double转bigDecimal精度问题double转bigDecimal精度问题需要用到bigDecimal的字符串构造来转float的精度:2^237位double的精度:2^5216位十进制转二进制存在精度差doubleg=12.35;BigDecimalbigG=newBigDecimal(g).setScale(1,BigDecimal.ROUND_HALF_UP);//…

大家好,又见面了,我是你们的朋友全栈君。

double转bigDecimal精度问题 需要用到bigDecimal的字符串构造来转

float的精度 : 2^23 7位

double的精度: 2^52 16位

十进制 转 二进制 存在精度差

double g= 12.35;

BigDecimal bigG=new BigDecimal(g).setScale(1, BigDecimal.ROUND_HALF_UP); //期望得到12.4

System.out.println(“test G:”+bigG.doubleValue());

test G:12.3

原因:

定义double g= 12.35; 而在计算机中二进制表示可能这是样:定义了一个g=12.34444444444444449,
new BigDecimal(g) g还是12.34444444444444449
new BigDecimal(g).setScale(1, BigDecimal.ROUND_HALF_UP); 得到12.3
正确的定义方式是使用字符串构造函数:
new BigDecimal(“12.35”).setScale(1, BigDecimal.ROUND_HALF_UP)

首先得从计算机本身去讨论这个问题。我们知道,计算机并不能识别除了二进制数据以外的任何数据。无论我们使用何种编程语言,在何种编译环境下工作,都要先 把源程序翻译成二进制的机器码后才能被计算机识别。以上面提到的情况为例,我们源程序里的2.4是十进制的,计算机不能直接识别,要先编译成二进制。但问 题来了,2.4的二进制表示并非是精确的2.4,反而最为接近的二进制表示是2.3999999999999999。原因在于浮点数由两部分组成:指数和尾数,这点如果知道怎样进行浮点数的二进制与十进制转换,应该是不难理解的。如果在这个转换的过程中,浮点数参与了计算,那么转换的过程就会变得不可预 知,并且变得不可逆。我们有理由相信,就是在这个过程中,发生了精度的丢失。而至于为什么有些浮点计算会得到准确的结果,应该也是碰巧那个计算的二进制与 十进制之间能够准确转换。而当输出单个浮点型数据的时候,可以正确输出,如

double d = 2.4;
System.out.println(d);

输出的是2.4,而不是2.3999999999999999。也就是说,不进行浮点计算的时候,在十进制里浮点数能正确显示。这更印证了我以上的想法,即如果浮点数参与了计算,那么浮点数二进制与十进制间的转换过程就会变得不可预知,并且变得不可逆。

事实上,浮点数并不适合用于精确计算,而适合进行科学计算。这里有一个小知识:既然float和double型用来表示带有小数点的数,那为什么我们不称 它们为“小数”或者“实数”,要叫浮点数呢?因为这些数都以科学计数法的形式存储。当一个数如50.534,转换成科学计数法的形式为5.053e1,它 的小数点移动到了一个新的位置(即浮动了)。可见,浮点数本来就是用于科学计算的,用来进行精确计算实在太不合适了。

在《Effective Java》这本书中也提到这个原则,float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用java.math.BigDecimal。使用BigDecimal并且一定要用String来够造。

BigDecimal用哪个构造函数?
BigDecimal(double val)
BigDecimal(String val)
上面的API简要描述相当的明确,而且通常情况下,上面的那一个使用起来要方便一些。我们可能想都不想就用上了,会有什么问题呢?等到出了问题的时候,才发现参数是double的构造方法的详细说明中有这么一段:
Note: the results of this constructor can be somewhat unpredictable. One might assume that new BigDecimal(.1) is exactly equal to .1, but it is actually equal to .1000000000000000055511151231257827021181583404541015625. This is so because .1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the long value that is being passed in to the constructor is not exactly equal to .1, appearances nonwithstanding.
The (String) constructor, on the other hand, is perfectly predictable: new BigDecimal(“.1”) is exactly equal to .1, as one would expect. Therefore, it is generally recommended that the (String) constructor be used in preference to this one.
原来我们如果需要精确计算,非要用String来够造BigDecimal不可!

简单来说 精确计算 ,需要用到bigDeicmal的String 构造

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/135926.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 预测算法用java实现吗_java 数据结构与算法

    预测算法用java实现吗_java 数据结构与算法常见的预测算法有1.简易平均法,包括几何平均法、算术平均法及加权平均法;2.移动平均法,包括简单移动平均法和加权移动平均法;3,指数平滑法,包括一次指数平滑法和二次指数平滑法,三次指数平滑法;4,线性回归法,包括一元线性回归和二元线性回归,下面我一一的简单介绍一下各种方法。 4P5?.C(B4j”^5_2h  一,简易平均法,是一种简便的时间序列法。是以一定观察期的数据求得

    2025年6月18日
    0
  • postman调试rpc接口

    postman调试rpc接口使用postman测试RPC接口PostMan如何调用RPC接口(postman下载)PostMan如何调用RPC接口接口调试之Postman使用方法详解

    2022年10月13日
    0
  • 小米BL不解锁刷机「建议收藏」

    小米BL不解锁刷机「建议收藏」关于小米NOTE顶配近期解锁的问题中发现还有很多人不会用9008模式刷机,现出个简单教程方便米粉们救砖。硬件:小米NOTE顶配手机win10系统的电脑手机与电脑相连的数据线软件:老版本的miflash(版本号:2015.10.28。0)最新版本miflash最新解BL锁工具或者小米助手(用来装驱动)开发版6.17及以前的线刷包随便下一个一个你最终想刷的版本(推荐最新稳定版)…

    2022年4月30日
    165
  • docker的端口映射_docker修改端口映射

    docker的端口映射_docker修改端口映射1.downloadimage:docker@default:/root#dockerpullmikeraab/hello-earth:latest2.createandstartcontainer(docker主机IP:192.168.99.101)a)默认大写-P自动映射$docker@default:/root#dockerrun-d

    2022年10月17日
    1
  • yum apache mysql php 配置_Linux Apache php MySQL 安装配置(Centos 6.4 yum安装)「建议收藏」

    yum apache mysql php 配置_Linux Apache php MySQL 安装配置(Centos 6.4 yum安装)「建议收藏」一、yum准备1.Yum(全称为YellowdogUpdater,Modified)是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器。基于RPM包管理,能够从指定的服务器自动下载RPM包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软件包,无须繁琐地一次次下载、安装。2.在安装软件时报’Couldn’tresolvehost’mirrorli…

    2022年7月12日
    12
  • tcp和udp的面试题_adp转化为amp

    tcp和udp的面试题_adp转化为amp相同点UDP协议和TCP协议都是传输层协议。TCP(TransmissionControlProtocol,传输控制协议)提供的是面向连接,可靠的字节流服务。即客户和服务器交换数据前,必须现在双方之间建立一个TCP连接,之后才能传输数据。并且提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。UDP(UserDataProtocol,用户数据报协议…

    2022年9月17日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号