BigDecimal创建应使用String参数构造方法或value of方法,否则会有精度丢失

本文主要是介绍BigDecimal创建应使用String参数构造方法或value of方法,否则会有精度丢失,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、BigDecimal.valueOf(double val):

这个方法是专门为浮点数设计的,它试图为给定的 double 值提供一个精确的 BigDecimal 表示。
当你传递一个 double 值给 valueOf 方法时,它并不直接使用该 double 的二进制表示。相反,它首先检查这个 double 是否能精确地表示为长整数(即没有小数部分),如果是,则使用长整数来构建 BigDecimal。
如果 double 值包含小数部分,则 valueOf 方法会使用一个更精确的算法来将 double 转换为 BigDecimal,这通常涉及将 double 分解为它的各个部分(符号、指数、尾数等),并据此构造 BigDecimal。
因此,对于 BigDecimal.valueOf(0.01),它通常会给出精确的结果,因为该值可以相对容易地以精确的方式转换为 BigDecimal。

二、new BigDecimal(double val):

当你使用这种构造函数时,BigDecimal 直接使用传入的 double 值的二进制表示来构建 BigDecimal。
但是,由于许多 double 值(尤其是小数)在二进制中不能精确表示(就像十进制中的 1/3 不能精确表示为有限小数一样),因此这种转换可能会导致精度损失。
这就是为什么直接使用 new BigDecimal(0.01) 可能会得到一个有轻微精度损失的结果的原因。
总之,为了避免在将浮点数转换为 BigDecimal 时出现精度问题,最好使用 BigDecimal.valueOf(double val) 方法,而不是直接使用 new BigDecimal(double val) 构造函数。

三、new BigDecimal(“0.01”):

这个构造函数直接接受一个字符串参数。
字符串 “0.01” 在内存中是以字符数组的形式存储的,每个字符都有一个明确的ASCII值。
BigDecimal 的这个构造函数会解析这个字符串,按照十进制数制规则来构建内部的数值表示。
因为字符串精确地表示了数字0.01,所以这种方式没有精度损失。

四、new BigDecimal(“0.01”)与BigDecimal.valueof(0.01)创建时底层有什么区别吗

在比较 new BigDecimal(“0.01”) 和 BigDecimal.valueOf(0.01) 创建 BigDecimal 对象时底层的区别时,实际上有一点需要澄清:BigDecimal.valueOf(0.01) 并不直接接受一个 double 类型的字面量作为参数,而是接受一个 double 类型的值作为参数,但这个值通常是通过字面量或其他方式(如计算)得到的。
不过,为了回答你的问题,我们可以从它们如何处理参数和内部实现的角度来讨论:
new BigDecimal(“0.01”):
这个构造函数直接接受一个字符串参数。
字符串 “0.01” 在内存中是以字符数组的形式存储的,每个字符都有一个明确的ASCII值。
BigDecimal 的这个构造函数会解析这个字符串,按照十进制数制规则来构建内部的数值表示。
因为字符串精确地表示了数字0.01,所以这种方式没有精度损失。

BigDecimal.valueOf(0.01):
这个静态方法接受一个 double 类型的参数(尽管这里你写的是一个 double 字面量0.01,但它在被传递给方法之前已经被转换成了 double 类型的值)。
这个 double 值在内存中是以IEEE 754浮点数格式存储的,可能不是0.01的精确表示。
但是,BigDecimal.valueOf 方法并没有直接使用这个 double 值的二进制表示来构建 BigDecimal。相反,它使用了一种更精确的方式来处理这个 double 值。
具体来说,valueOf 方法会检查这个 double 值是否可以精确地表示为一个长整数(即没有小数部分)。如果可以,它就直接使用长整数来构建 BigDecimal。如果不能,它会将 double 值分解为它的各个部分(符号、指数、尾数等),并据此精确地构建 BigDecimal。
因此,虽然你传递的是一个 double 值给 valueOf 方法,但该方法会尽量避免由于 double 不精确表示导致的精度损失。
总结来说,虽然 new BigDecimal(“0.01”) 和 BigDecimal.valueOf(0.01) 在表面上看起来都接受了一个表示0.01的参数,但它们在底层处理这个参数的方式是不同的。new BigDecimal(“0.01”) 直接解析字符串来构建 BigDecimal,而 BigDecimal.valueOf(0.01) 则使用了一种更精确的方式来处理 double 值,以避免精度损失。

五、BigDecimal.valueof(0.01)为啥没有精度问题,而new BigDecimal(0.01)有精度问题

BigDecimal是Java中用于解决浮点数运算精度问题的一个类,它提供了精确的数值运算能力。在处理涉及精度要求较高的场合,如金融计算时,BigDecimal的使用尤为重要。关于BigDecimal.valueOf(0.01)new BigDecimal(0.01)在精度问题上的差异,可以从以下几个方面进行分析:

  1. 计算机存储机制

    • 二进制表示:计算机内部使用二进制系统来表示和存储所有的数据,包括十进制的浮点数。由于二进制无法精确表示某些十进制小数,因此在转换过程中可能会产生精度损失[1]。
    • 浮点数表示:计算机中的浮点数由指数和尾数两部分组成,这种表示方法可能会导致一些浮点数运算产生误差[3]。
  2. 构造函数差异

    • BigDecimal.valueOf(double val):这个静态方法在底层实际上是将传入的double值先转换为字符串,然后再创建BigDecimal对象。这样做的好处是避免了直接使用double值可能带来的精度损失[4]。
    • new BigDecimal(double val):使用这个构造函数会直接根据传入的double值创建一个BigDecimal对象,但由于double值本身的精度问题,创建的BigDecimal对象可能会包含不精确的值[3]。
  3. 精度丢失风险

    • 直接使用double:当直接使用double类型的字面量作为参数时,可能会因为二进制表示的限制而引入精度误差。
    • 字符串转换:通过字符串创建BigDecimal可以避免这种精度丢失,因为字符串中的每个数字都是精确的。
  4. 推荐做法

    • 优先使用BigDecimal.valueOf():为了避免精度丢失,建议使用BigDecimal.valueOf()方法来创建BigDecimal对象[2][4]。
    • 使用字符串构造函数:或者使用new BigDecimal(String val)构造函数,将需要精确表示的浮点数先转换为字符串,再创建BigDecimal对象。
  5. 阿里巴巴Java开发手册建议

    • 避免使用基本数据类型:《阿里巴巴 Java 开发手册》中提到,浮点数之间的等值判断不应该使用基本数据类型的==来比较,因为这可能会因为精度问题导致错误的比较结果[1]。
    • 使用BigDecimal进行精确计算:手册中还提到,涉及到钱等需要精确计算结果的场景应该使用BigDecimal来进行运算。
  6. 实际案例

    • 金融计算:在金融领域,比如货币的加减乘除,精确到分的计算是必须的,这时候使用BigDecimal可以保证计算的准确性。
    • 科学计算:在科学计算中,对精度的要求也非常高,使用BigDecimal可以避免因为浮点数的精度问题导致的计算错误。
  7. 注意事项

    • 除法运算:在使用BigDecimal进行除法运算时,应该注意使用带有三个参数的divide方法,并选择合适的舍入模式,以避免无法除尽时出现的异常[1]。
    • 大小比较:使用compareTo方法进行大小比较,而不是使用==来判断两个BigDecimal对象是否相等。
  8. 其他方法

    • add、subtract、multiply、divide:这些方法分别用于执行加法、减法、乘法和除法运算,它们保证了运算的精确性[1]。
    • toString、doubleValue、floatValue、longValue、intValue:这些方法用于将BigDecimal对象转换为其他类型的对象,但需要注意的是转换后的对象可能无法保持原有的精度。

综上所述,BigDecimal.valueOf(0.01)没有精度问题是因为它通过将double值转换为字符串的方式来创建BigDecimal对象,从而避免了直接使用double值可能带来的精度损失。而new BigDecimal(0.01)有精度问题的原因在于它直接使用了可能存在精度误差的double值来创建BigDecimal对象。因此,在实际开发中,为了确保精度,应优先考虑使用BigDecimal.valueOf()方法或通过字符串构造函数来创建BigDecimal对象。

这篇关于BigDecimal创建应使用String参数构造方法或value of方法,否则会有精度丢失的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1036189

相关文章

C语言中联合体union的使用

本文编辑整理自: http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=179471 一、前言 “联合体”(union)与“结构体”(struct)有一些相似之处。但两者有本质上的不同。在结构体中,各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和。而在“联合”中,各成员共享一段内存空间, 一个联合变量

ESP32 esp-idf esp-adf环境安装及.a库创建与编译

简介 ESP32 功能丰富的 Wi-Fi & 蓝牙 MCU, 适用于多样的物联网应用。使用freertos操作系统。 ESP-IDF 官方物联网开发框架。 ESP-ADF 官方音频开发框架。 文档参照 https://espressif-docs.readthedocs-hosted.com/projects/esp-adf/zh-cn/latest/get-started/index

问题:第一次世界大战的起止时间是 #其他#学习方法#微信

问题:第一次世界大战的起止时间是 A.1913 ~1918 年 B.1913 ~1918 年 C.1914 ~1918 年 D.1914 ~1919 年 参考答案如图所示

[word] word设置上标快捷键 #学习方法#其他#媒体

word设置上标快捷键 办公中,少不了使用word,这个是大家必备的软件,今天给大家分享word设置上标快捷键,希望在办公中能帮到您! 1、添加上标 在录入一些公式,或者是化学产品时,需要添加上标内容,按下快捷键Ctrl+shift++就能将需要的内容设置为上标符号。 word设置上标快捷键的方法就是以上内容了,需要的小伙伴都可以试一试呢!

Tolua使用笔记(上)

目录   1.准备工作 2.运行例子 01.HelloWorld:在C#中,创建和销毁Lua虚拟机 和 简单调用。 02.ScriptsFromFile:在C#中,对一个lua文件的执行调用 03.CallLuaFunction:在C#中,对lua函数的操作 04.AccessingLuaVariables:在C#中,对lua变量的操作 05.LuaCoroutine:在Lua中,

大学湖北中医药大学法医学试题及答案,分享几个实用搜题和学习工具 #微信#学习方法#职场发展

今天分享拥有拍照搜题、文字搜题、语音搜题、多重搜题等搜题模式,可以快速查找问题解析,加深对题目答案的理解。 1.快练题 这是一个网站 找题的网站海量题库,在线搜题,快速刷题~为您提供百万优质题库,直接搜索题库名称,支持多种刷题模式:顺序练习、语音听题、本地搜题、顺序阅读、模拟考试、组卷考试、赶快下载吧! 2.彩虹搜题 这是个老公众号了 支持手写输入,截图搜题,详细步骤,解题必备

Vim使用基础篇

本文内容大部分来自 vimtutor,自带的教程的总结。在终端输入vimtutor 即可进入教程。 先总结一下,然后再分别介绍正常模式,插入模式,和可视模式三种模式下的命令。 目录 看完以后的汇总 1.正常模式(Normal模式) 1.移动光标 2.删除 3.【:】输入符 4.撤销 5.替换 6.重复命令【. ; ,】 7.复制粘贴 8.缩进 2.插入模式 INSERT

电脑不小心删除的文件怎么恢复?4个必备恢复方法!

“刚刚在对电脑里的某些垃圾文件进行清理时,我一不小心误删了比较重要的数据。这些误删的数据还有机会恢复吗?希望大家帮帮我,非常感谢!” 在这个数字化飞速发展的时代,电脑早已成为我们日常生活和工作中不可或缺的一部分。然而,就像生活中的小插曲一样,有时我们可能会在不经意间犯下一些小错误,比如不小心删除了重要的文件。 当那份文件消失在眼前,仿佛被时间吞噬,我们不禁会心生焦虑。但别担心,就像每个问题

Lipowerline5.0 雷达电力应用软件下载使用

1.配网数据处理分析 针对配网线路点云数据,优化了分类算法,支持杆塔、导线、交跨线、建筑物、地面点和其他线路的自动分类;一键生成危险点报告和交跨报告;还能生成点云数据采集航线和自主巡检航线。 获取软件安装包联系邮箱:2895356150@qq.com,资源源于网络,本介绍用于学习使用,如有侵权请您联系删除! 2.新增快速版,简洁易上手 支持快速版和专业版切换使用,快速版界面简洁,保留主

如何免费的去使用connectedpapers?

免费使用connectedpapers 1. 打开谷歌浏览器2. 按住ctrl+shift+N,进入无痕模式3. 不需要登录(也就是访客模式)4. 两次用完,关闭无痕模式(继续重复步骤 2 - 4) 1. 打开谷歌浏览器 2. 按住ctrl+shift+N,进入无痕模式 输入网址:https://www.connectedpapers.com/ 3. 不需要登录(也就是