惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
小众软件
小众软件
Engineering at Meta
Engineering at Meta
博客园 - 三生石上(FineUI控件)
WordPress大学
WordPress大学
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
V2EX
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Google DeepMind News
Google DeepMind News
Security Archives - TechRepublic
Security Archives - TechRepublic
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Check Point Blog
aimingoo的专栏
aimingoo的专栏
罗磊的独立博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
MongoDB | Blog
MongoDB | Blog
L
LINUX DO - 热门话题
酷 壳 – CoolShell
酷 壳 – CoolShell
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Help Net Security
Martin Fowler
Martin Fowler
G
GRAHAM CLULEY
Simon Willison's Weblog
Simon Willison's Weblog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - Franky
V
Vulnerabilities – Threatpost
云风的 BLOG
云风的 BLOG
博客园_首页
C
Cybersecurity and Infrastructure Security Agency CISA
量子位
Stack Overflow Blog
Stack Overflow Blog
Recent Announcements
Recent Announcements
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
I
Intezer
Scott Helme
Scott Helme
A
About on SuperTechFans
博客园 - 司徒正美
Hacker News: Ask HN
Hacker News: Ask HN
The GitHub Blog
The GitHub Blog
Forbes - Security
Forbes - Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
The Cloudflare Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Spread Privacy
Spread Privacy
T
Tailwind CSS Blog
S
Security Affairs
宝玉的分享
宝玉的分享

Yulin Lewis' Blog

cron表达式 cmd - 常用命令 Eureka问题汇总 Excel常见用法 shell脚本常用语法 Linux常用命令 别了,向晚 必胜客自助餐 Prometheus简易入门 Chrome问题汇总 SSH命令问题汇总 PGP加解密 Apollo问题汇总 GitHub问题汇总 SmartGit问题汇总 HttpClient问题汇总 Oculus Quest2食用指南 背包英雄:匕首流无尽模式详细攻略 Linux问题汇总 Postman问题汇总 别了,珈乐 桌面窗口管理器占用内存过高 ELK系列(6) - Elasticsearch常用接口 ELK系列(5) - Elasticsearch性能调优 MyBatis问题汇总 PostgreSQL - SQL调优方案 Java - 字符编码 Spring Data Redis问题汇总 lombok问题汇总
Java数值问题汇总
雨临Lewis · 2022-01-10 · via Yulin Lewis' Blog

double转成BigDecimal的精度损失问题

如果直接用构造方法将double数值转成BigDecimal,可能存在损失精度的问题:

1
2
3
4
5
6
final BigDecimal b1 = new BigDecimal(0.48);
final BigDecimal b2 = BigDecimal.valueOf(0.48);
// 0.479999999999999982236431605997495353221893310546875
System.out.println(b1);
// 0.48
System.out.println(b2);

可以看到,第一种方式丢失了精度。原因是0.48这个浮点数实际上并不能非常精确的表示0.48这个double值,因为二进制表示的小数部分长度是有限的。

为了避免丢失精度,需要调用官方提供的valueOf方法,实际上底层是将浮点数先转成字符串,再转成BigDecimal:

1
2
3
4
5
6
7
    public static BigDecimal valueOf(double val) {
        // Reminder: a zero double returns '0.0', so we cannot fastpath
        // to use the constant ZERO.  This might be important enough to
        // justify a factory approach, a cache, or a few private
        // constants, later.
        return new BigDecimal(Double.toString(val));
    }

因此,也可以直接传入字符串来构造BigDecimal:

1
2
3
final BigDecimal b3 = new BigDecimal("0.48");
// 0.48
System.out.println(b3);

判断BigDecimal是否相等

在判断两个BigDecimal是否相等时,不能使用equals(),原因是equals()除了比较数值是否相等外,还会比较标度scale。从业务来考虑,通常只需要对比数值就行了,此时应该用compareTo()方法:

1
2
3
4
5
6
7
8
public static void main(final String[] args) {
    BigDecimal a = new BigDecimal("0.1");
    BigDecimal b = new BigDecimal("0.10");
	// false
    System.out.println(a.equals(b));
	// 0
    System.out.println(a.compareTo(b));
}

compareTo()会返回-1,0和1,从上述代码可以看出来,a和b的标度不同,a的标度是0.1,b的标度是0.10,所以equals()返回的false,但是由于二者数值相同,所以compareTo()返回了0。

警告

本文最后更新于 February 24, 2022,文中内容可能已过时,请谨慎使用。

赞赏支持

微信打赏 支付宝打赏