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

推荐订阅源

C
Check Point Blog
AI
AI
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
U
Unit 42
Vercel News
Vercel News
Stack Overflow Blog
Stack Overflow Blog
P
Proofpoint News Feed
Microsoft Security Blog
Microsoft Security Blog
The GitHub Blog
The GitHub Blog
WordPress大学
WordPress大学
Martin Fowler
Martin Fowler
博客园 - 【当耐特】
B
Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
F
Full Disclosure
Google DeepMind News
Google DeepMind News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Help Net Security
Recorded Future
Recorded Future
N
News and Events Feed by Topic
雷峰网
雷峰网
V
Vulnerabilities – Threatpost
Schneier on Security
Schneier on Security
aimingoo的专栏
aimingoo的专栏
S
Schneier on Security
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
O
OpenAI News
Project Zero
Project Zero
罗磊的独立博客
G
GRAHAM CLULEY
腾讯CDC
P
Privacy International News Feed
V
V2EX
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Hugging Face - Blog
Hugging Face - Blog
爱范儿
爱范儿
H
Heimdal Security Blog
L
LINUX DO - 热门话题
Forbes - Security
Forbes - Security
美团技术团队
MongoDB | Blog
MongoDB | Blog
Security Latest
Security Latest
M
MIT News - Artificial intelligence
T
Tor Project blog
Cisco Talos Blog
Cisco Talos Blog
宝玉的分享
宝玉的分享
T
Threat Research - Cisco Blogs
TaoSecurity Blog
TaoSecurity Blog

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,文中内容可能已过时,请谨慎使用。

赞赏支持

微信打赏 支付宝打赏