《Java 100 天进阶之路》第40篇:浮点数转成十进制问题

微信支付金额转换陷阱:如何避免浮点数精度导致的64位整数校验失败 本文深入剖析了微信支付开发中因浮点数精度丢失导致金额转换错误,进而引发64位有符号整数校验失败的常见陷阱。文章以323.40元等具体金额为例,解释了问题根源在于计算机二进制存储特性,并提供了PHP、Java、Python等多语言的实战解决方案与架构层面的最佳实践,帮助开发者从根本上杜绝此类问题。 阅读详情

第40篇:浮点数转成十进制问题

📌 系列导航:《Java 100 天进阶之路》完整目录 |
⬅️ 上一篇:第39篇:Java泛型方法的定义和使用 |
➡️ 下一篇:第41篇:GET和POST的区别、堆和栈的区别


一、核心知识点

  • 浮点数的二进制表示(IEEE 754 标准)
  • 精度丢失原因:十进制小数无法用二进制精确表示(如 0.1)
  • 典型问题:0.1 + 0.2 != 0.3
  • 解决方案:BigDecimal、整数转换、误差阈值比较
  • BigDecimal 的正确使用(用字符串构造)

二、通俗讲解(1分钟开心学)

1. 为什么浮点数不精确?

计算机使用二进制存储数据。十进制小数在二进制中可能是无限循环的,比如 0.1 转换为二进制是 0.0001100110011...(无限循环)。内存有限,只能近似存储,所以运算时会产生微小误差。

2. 经典案例

System.out.println(0.1 + 0.2); // 0.30000000000000004

3. 如何正确比较浮点数?

  • 误差范围法:判断两个浮点数差的绝对值小于一个很小的数(如 1e-6)。
  • BigDecimal:精确的十进制运算,适合金融计算。
  • 整数转换:将小数转为整数计算,例如用“分”代替“元”。

4. BigDecimal 陷阱

new BigDecimal(0.1) 仍然不精确,因为 0.1 本身已经是不精确的 double。正确方式:new BigDecimal("0.1") 或 BigDecimal.valueOf(0.1)。

生活类比:
浮点数误差就像你用一米的尺子去量一根木棍,木棍长度是 0.1 米,但你的尺子最小刻度是 0.125 米(二进制分数近似),你只能量出 0.125 米或 0.0 米。多次测量后误差累积。

三、实操代码案例 + 场景说明

场景:做电商的金额计算,必须精确到分。

import java.math.BigDecimal;
import java.math.RoundingMode;

public class FloatDecimalDemo {
    public static void main(String[] args) {
        // 1. 浮点数误差演示
        double a = 0.1;
        double b = 0.2;
        double c = 0.3;
        System.out.println(a + b == c);   // false
        System.out.println(a + b);        // 0.30000000000000004
        
        // 2. 误差比较法
        final double EPS = 1e-6;
        if (Math.abs((a + b) - c) < EPS) {
            System.out.println("近似相等");
        }
        
        // 3. BigDecimal 正确使用
        BigDecimal bd1 = new BigDecimal("0.1");
        BigDecimal bd2 = new BigDecimal("0.2");
        BigDecimal sum = bd1.add(bd2);
        System.out.println(sum);               // 0.3
        System.out.println(sum.compareTo(new BigDecimal("0.3")) == 0); // true
        
        // 4. BigDecimal 做金融计算(售价、折扣)
        BigDecimal price = new BigDecimal("19.99");
        BigDecimal discount = new BigDecimal("0.85");
        BigDecimal finalPrice = price.multiply(discount).setScale(2, RoundingMode.HALF_UP);
        System.out.println("折后价:" + finalPrice); // 16.99
        
        // 5. 整数转换法(金额用分表示)
        long priceInCents = 1999;  // 19.99 元
        long discountPercent = 85; // 八五折
        long finalCents = priceInCents * discountPercent / 100;
        System.out.println("折后分:" + finalCents); // 1699 分 = 16.99 元
    }
}

四、避坑要点

错误/误区后果正确做法
直接用 == 比较浮点数可能永远为 false(即使数值接近)使用误差范围或 BigDecimal
new BigDecimal(0.1)得到的不是精确 0.1用 new BigDecimal("0.1") 或 BigDecimal.valueOf(0.1)
在循环中累加浮点数误差累积,结果偏差大累加用 BigDecimal 或整数
浮点数直接输出或格式化不控制精度显示很多位小数用 String.format("%.2f", d) 或 BigDecimal.setScale

五、面试高频考点

Q1:为什么 0.1 + 0.2 != 0.3?

0.1 和 0.2 在二进制中是无限循环小数,计算机只能近似存储,相加后误差累积导致结果略大于 0.3。

Q2:如何正确比较浮点数?

  1. 用 BigDecimal;2. 设定误差阈值 Math.abs(x - y) < 1e-6;3. 转换为整数(如货币用分)。

Q3:BigDecimal 和 double 的区别?

BigDecimal 精确十进制,适合金融计算,但性能较低;double 近似值,性能高,适合科学计算。

六、练习题

  1. 计算:1.0 - 0.9 的结果是什么?为什么?
  2. 编程:使用 BigDecimal 计算商品总价:单价 19.99,数量 3,折扣 9.0 折,保留两位小数。
  3. 简答:为什么银行系统使用 BigDecimal 而不是 double?

📊 你的学习进度

  • 当前:第40篇 / 共44篇 · 第六阶段:NIO、泛型、JVM内幕、字节码(第36~44篇)
  • ✅ 已完成:第1~39篇
  • 📖 正在学:第40篇
  • ⏳ 待学习:第41~44篇

👉 📚 完整目录 & 学习指南 | 🔥 订阅本专栏,不错过每一篇

💡 本专栏每篇都包含:避坑表 + 面试高频考点 + 练习题。每天30分钟,100天拿offer!


👉 下一篇文章预告

《第41篇:GET和POST的区别、堆和栈的区别》

内容简介:GET vs POST(参数位置/长度/安全/幂等)、堆与栈存储内容、栈溢出与堆溢出。

💡 学完这篇,你将彻底分清网络请求的两种方式和JVM内存的两大区域。

📌 《Java 100 天进阶之路 | 从入门到上岗就业》 每天一篇,建议收藏 + 关注,一起100天拿offer!
👉 点击关注我,更新后第一时间收到推送!
📌 除了《Java 100 天进阶之路 | 从入门到上岗就业》系列文章,我也在深挖智能物流实战(出版社WMS、托盘调度、机器学习落地)。如果你对技术在不同领域的实战感兴趣,欢迎点击我的头像,看看专栏《出版社物流WMS智能调度实战》。技术相通,思路可鉴。

微信支付金额精度陷阱:如何避免浮点数计算导致的JSON映射错误 本文深入探讨了微信支付开发中常见的金额精度问题,特别是浮点数计算导致的JSON映射错误。通过分析64位有符号整数的要求,提供了round()函数、number_format()格式化和整数转换三种解决方案,并对比了它们的性能与精度。文章还涵盖了其他语言的实现方法及微信支付中的其他金额陷阱,帮助开发者避免常见错误,确保支付系统的稳定性。 阅读详情

相关推荐

100天精通Python(基础篇)——第4天:数据类型全解析_从基础到转换

数据类型全解析_从基础到转换

努力让自己发光,对的人才能迎着光而来 11万+

《2026全新 | Java 100 天进阶之路:从零基础到上岗就业,108篇完整学习地图》

摘要:不背八股文,不堆概念。44篇基础 + 64篇进阶(共108篇),100天助你达到Java就业水平,从容面对技术面试。 👉 零基础入门 / 校招社招突击 / 1-3年Java后端提升 / 想系统复盘全栈知识的开发者。

折哥|智能物流与Java实战,副高数据库工程师。深耕出版社物流WMS/OMS(线体/立库/VGA),也分享Java进阶与OMS电商对接。Oracle→PG实战派。相信沉淀可迁移能力,分享通用技术,不藏不虚。 9582

CentOS7无外网环境下MySQL8.0完整离线部署指南

本文详细介绍了在CentOS7无外网环境下,如何通过MySQL8.0二进制包进行完整离线部署。指南涵盖了从环境准备、依赖安装、用户与目录创建,到数据库初始化、服务配置及远程访问设置的全过程,并提供了关键的避坑技巧,帮助企业运维人员在内网环境中高效、稳定地搭建MySQL数据库服务。

xxx12的博客 1027

《Java 100 天进阶之路》第39篇:Java泛型方法的定义和使用

本文介绍了Java泛型方法的核心概念和使用场景。主要内容包括:1)泛型类、接口和方法的定义;2)类型参数和有界类型;3)类型擦除原理;4)通配符的使用及PECS原则。通过代码示例演示了泛型方法在数组交换、最大值比较、列表操作等场景的应用,并总结了常见误区。文章还提供了面试高频考点解析和练习题,帮助读者掌握泛型编程技巧。

折哥|智能物流与Java实战,副高数据库工程师。深耕出版社物流WMS/OMS(线体/立库/VGA),也分享Java进阶与OMS电商对接。Oracle→PG实战派。相信沉淀可迁移能力,分享通用技术,不藏不虚。 529

手把手教你搭建日本亚马逊CVV钓鱼系统(含自动验证功能)

本文详细介绍了电商平台安全防护的关键实践,重点讲解了如何构建自动化风控系统。内容包括基础架构设计、用户行为分析、交易风险评估模型构建、验证机制实现以及系统部署优化,帮助电商平台有效识别和防范安全威胁,同时提升用户体验。

weixin_30952535的博客 811

如何在windows下使用cmake编译源码

MyProject/└── build/在MyProject目录下创建并编辑。创建build目录并进入。使用cmake命令生成构建文件。使用适当的命令编译项目。运行生成的可执行文件。

cdj444asdg的博客 3339

java 浮点数 精度_Java浮点数计算精度问题总结

Java浮点数计算精度问题总结首先看看下面几个简单的加法计算的输出结果:System.out.println(0.1 + 0.2); //输出:0.30000000000000004System.out.println(1.1 + 1.2); //输出:2.3System.out.println(0.1f + 0.2f);//输出:0.3浮点数计算可能出问题的根本原因:IEEE754的浮点数世...

weixin_35689681的博客 1974

Zotero+WPS文献引用跳转功能缺失?3分钟教你用VBA宏搞定(附完整代码)

本文针对WPS用户使用Zotero时文献引用无法点击跳转的痛点,提供了一套完整的VBA宏解决方案。通过解析Zotero的域代码,自动在文内引用和文末参考文献之间创建超链接,实现一键跳转,极大提升了学术写作与文献查阅的效率。

weixin_28419039的博客 659

JavaScript 浮点数精度问题

浮点数精度问题是所有使用 IEEE 754 标准的编程语言(包括 JavaScript、Java、Python 等)都会遇到的常见问题

pan303507479的博客 761

K8S部署Java项目(Gitlab CI/CD自动化部署终极版)

每个人都有惰性,但不断学习是好好生活的根本,共勉!

感谢阅读 6950

MATLAB 车牌识别系统

车牌识别系统利用计算机视觉和图像处理技术,自动识别车辆牌照上的字符信息。本系统基于 MATLAB 实现车牌识别,包括图像预处理、车牌定位、字符分割、字符识别等模块。车牌识别系统是实现智能交通和公共安全的重要手段,具有广泛的应用前景。MATLAB 提供了丰富的工具和函数,可以方便地进行算法仿真和系统开发。

走向CTO的路上... 626

java浮点数存储方式_一文帮你读懂Java浮点数的存储原理

前言Java数值分整数和浮点数,前一篇文章已经解析了Java整数的存储原理,本篇将接着解析浮点数在计算机里的存储原理。Java浮点数分单精度类型( float)和双精度类型(double),float 数据占用 32bit,double 数据占用 64bit。Java浮点数标准java中浮点数采用的IEEE754标准,该标准的全称为IEEE二进制浮点数算术标准。这个标准规定的存储格式是这样的:符号...

weixin_42356307的博客 1037

85-Halcon-- gen_cam_par_area_scan_division 函数功能(生成面阵相机镜头参数)

Halcon的gen_cam_par_area_scan_division算子用于生成面阵相机的镜头参数,支持除法畸变模型。该算子输出包含9个参数的元组,包括焦距(Focus)、畸变系数(Kappa)、像素尺寸(Sx,Sy)、主点坐标(Cx,Cy)和图像尺寸。文中详细解析了各参数含义、数学原理(包括畸变矫正公式和坐标转换),并提供了三个工业应用案例:高精度芯片尺寸测量、机器人焊接引导和大视野汽车表面检测。最后给出了完整的相机标定流程,涵盖参数生成、畸变校正和标定配置步骤,适用于工业视觉系统的精确标定需求。

weixin_45590420的博客 909

单精度浮点数 float、双精度浮点数 double

内容导视:之前漏掉了小数对应的二进制,现补上。二进制转十进制从个位数开始向左计算,个位数乘以 2 的 0 次方,十位数乘以 2 的 1 次方,百位数乘以 2 的 2 次方…从十分位开始向右计算,十分位乘以 2 的 -1 次方,百分位乘以 2 的 -2 次方…然后将每个式子的结果相加。例 1:0b101.11 转为十进制 例 2:0b111.01 转为十进制 可以看到小数部分都是由 0.5、0.25、0.125、0.0625… 等数组合表示,前面的系数 1 或 0,0.625 = 1 * 0.5 + 0 *

什么美哟有 1万+

Vibe coding 氛围编程:编程就像聊天一样,低代码开发时代来了?

Vibe coding:编程就像聊天一样,低代码开发时代来了!

Code_流苏:在代码中寻诗意,在实践中觅真知 4785

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Java浮点数计算精度问题总结

Java浮点数计算精度问题总结 首先看看下面两个简单计算分别会输出什么样的结果,如果你觉得都会输出0.3,那么你应该耐心看完本文。 System.out.println(0.1 + 0.2); //输出:0.30000000000000004 System.out.println(0.1f + 0.2f);//输出:0.3 本文讨论下面这些问题: 为什么浮

lang_niu的专栏 1171

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

java ieee_IEEE浮点数表示法(zz)

posted on 2006-10-08 22:27 凌宇 阅读(2791) 评论(4) 编辑 收藏FeedBack:#re: IEEE浮点数表示法(zz)2006-10-08 22:29 | 凌宇IEEE浮点数表示从存储结构和算法上来讲,double和float是一样的,不一样的地方仅仅是float是32位的,double是64位的,所以double能存储更高的精度。任何数据在内存中都是以...

weixin_36002881的博客 385

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Java 浮点数 float和double类型的表示范围和精度

隐约记得,浮点数判断大小好像有陷阱,因为底层的二进制数不能精确表示所有的小数。有事后会产生让人觉得莫名其妙的事情。

张小琦的博客专栏 8万+

16进制转浮点数工具_一文帮你读懂Java浮点数的存储原理

前言Java数值分整数和浮点数,前一篇文章已经解析了Java整数的存储原理,本篇将接着解析浮点数在计算机里的存储原理。Java浮点数分单精度类型( float)和双精度类型(double),float 数据占用 32bit,double 数据占用 64bit。Java浮点数标准java中浮点数采用的IEEE754标准,该标准的全称为IEEE二进制浮点数算术标准。这个标准规定的存储格式是这样的:符号...

weixin_34452012的博客 785

JavaScript浮点数运算的精度问题

之前在做浮点数计算时,偶然发现计算结果有误差,度娘了解了下,补充整理了下。 误差是什么样子的呢?举例 console.log(0.1+0.2); // 0.30000000000000004 事实上在很多的编程语言当中都存在着或多或少的精度问题,只不过类似于Java这些语言经历这么多年,已经封装好了很多方法来解决这个问题了。而JavaScript是一门弱类型的语言,从设计思...

banliyou9765的博客 262

《14天从0到1学Java》第一天之07Java变量和常量

这个是一套系列教程,一共14天,每天8篇,每篇需要5分钟。也就是说,你需要每天抽出40分钟来看教程,坚持14天就可以,轻松玩转JavaSE。 我是Feri,我为自己代言,专注IT职场研发和教育N年,希望对于你的入门,有所帮助! 本篇目录一、常量二、变量2.1 变量的概述2.2 变量的声明和初始化2.3 变量的分类2.4 局部变量和成员变量的区别 一、常量 常量:常见的数值类型(也称为数据常...

程序员Feri 435

Java浮点数误差与BigDecimal原理详解:0.1+0.2为何不等于0.3

在计算机系统中,浮点数的存储遵循IEEE 754标准,使用二进制表示小数时,很多十进制小数(如0.1)无法被有限位数精确表达,由此产生了精度损失。这种误差在Java的double与float运算中普遍存在,尤其在金额计算、费率统计等对精度要求极高的业务场景中,直接使用浮点数会导致账不平、对账失败等严重问题。BigDecimal作为Java提供的精确数值计算类,通过十进制字符串解析和任意精度整数存储,绕开了二进制近似表示,从根本上解决了浮点误差问题。掌握BigDecimal的创建方式、运算API、舍入模式及比

weixin_34252090的博客 402

Java BigDecimal:解决浮点数精度问题的终极方案

在计算机科学中,浮点数精度问题是一个普遍存在的技术挑战,尤其在金融计算和科学计算领域。由于IEEE 754二进制浮点表示法的固有缺陷,简单的十进制小数如0.1在计算机中会被转换为无限循环的二进制小数,导致计算误差。BigDecimal作为Java提供的精确计算工具类,通过基于任意精度整数和缩放因子的存储机制,彻底解决了这一问题。它不仅支持精确的四则运算和多种舍入模式,还能处理超大数运算。在金融系统、电商平台和科学计算等对精度要求极高的场景中,BigDecimal的正确使用是保证计算准确性的关键技术。掌握Bi

weixin_33898876的博客 315

16 bit float 存储_一文帮你读懂Java浮点数的存储原理

前言Java数值分整数和浮点数,前一篇文章已经解析了Java整数的存储原理,本篇将接着解析浮点数在计算机里的存储原理。Java浮点数分单精度类型( float)和双精度类型(double),float 数据占用 32bit,double 数据占用 64bit。Java浮点数标准java中浮点数采用的IEEE754标准,该标准的全称为IEEE二进制浮点数算术标准。这个标准规定的存储格式是这样的:符号...

weixin_39592137的博客 666

c++ 双精度浮点数转2进制_计算机组成原理 浮点数和定点数

如果你有 python 或者 node 的命令行终端,或者浏览器里面的 Console,你可以做个测试,输入 0.3 + 0.6 看下值究竟是多少。Welcome to Node.js v12.16.1.Type ".help" for more information.> 0.3+0.60.899999999999999932 bit 只能表示 2^32 次方个不同的数,大约 4...

weixin_36463451的博客 572

[转载]浮点数0.57 0.58 造出的坑爹问题

转载自:http://justjavac.iteye.com/blog/1864938今天看到 vb2005xu 提到了一个问题  浮点数0.57 0.58 造出的坑爹问题。  parseInt(0.59*100) // 59 parseInt(0.58*100) // 57 parseInt(0.57*100) // 56 parseInt(0.56*100) // 56  为什么会这

Mr_eee的专栏 1125
上一篇: 《Java 100 天进阶之路》第39篇:Java泛型方法的定义和使用
下一篇: Qoder 1.0 完全指南:从安装到Agents驱动开发实战
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值