关于浮点数与精确小数计算的理解
下面这篇文章探讨的是关于浮点数与精确小数计算的理解。
小数在大家的生活中太常见了,这玩意小学就教,计算机程序里也经常用到,所以它可能不太被人注意。
但现实是,如果你不了解小数在计算机的世界里是怎么玩的,你就很可能在程序中因错误使用小数而犯错。
本文不深入剖析小数在计算机中的表示形式(IEEE 754 规范),意在讲清楚计算机中使用小数会出现什么问题,以及解决方案。
浮点数带来的问题
假如你在面试,面试官看到你有和金融,银行相关的项目的经历,可能会问你记录存款和消费金额等与钱有关的数据时使用什么数据类型?
如果你能答上来BigDecimal等小数工具类的话,他可能会继续问你:为什么放着现成的float和double不用,要使用小数工具类呢?
这里就涉及到浮点数在计算机系统中存储的问题了。
我们可以通过自己熟悉的语言快速地重新浮点数计算不精确的现象,本文以Java为例进行展示:
public class Main { public static void main(String[] args){ System.out.println(0.01 + 0.09); System.out.println(1 - 0.32); System.out.println(1.015 * 100); } } //输出结果: 0.09999999999999999 0.6799999999999999 101.49999999999999
那么究竟为什么会出现这样的不精确现象呢?
众所周知计算机的世界是一个二进制的世界,计算机系统内部的一切数据终究会落实到0和1这两个数字上。但我们人类世界中基本都是使用十进制,要想把人类的问题交给计算机解决,就必须有一个把十进制数转换为二进制数的过程,浮点数的问题就出在这个转换的过程中。
想要把一个十进制的整数转换为二进制,简单!数学上只要对目标整数不断除以二,直到除尽或余数为1即可,这样的转换是精确的。其背后的原理是所有的整数都能通过2^n之和加上正负号来表示(n取所有正整数和0)
但是想要把一个十进制的小数转换为二进制,就不那么简单了。根本原因在于2^n之和加上正负号(n取所有负整数)不能表示所有的小数!
从数学上把一个小数从十进制转换为二进制,你需要对小数不断乘以二,直到得到1才算转换完成。事实上能完成这一转换的小数不多,大多数小数才乘以二的过程中都会进入一个循环的序列,导致无法精确地把一个小数从十进制转换为二进制。
解决浮点数问题,精确计算小数
既然我们已经知道了计算机能准确计算整数,但不能准确计算小数。那我们可以这样想:如果把小数转换为整数,让计算机计算整数,在得出精确的计算结果后再转换为小数,这样计算结果不就精确了吗?
按照这个思路,人们封装了精确计算小数的工具类,在Java中这个工具类叫做BigDecimal,我们可以通过一次Debug验证一下是否真的是这么干的:
public class Main { public static void main(String[] args){ BigDecimal bd1 = new BigDecimal("123.456"); BigDecimal bd2 = new BigDecimal("654.321"); BigDecimal result = bd1.add(bd2); System.out.println(result.toString()); } } //输出结果: 777.777
参考文章:
https://zhuanlan.zhihu.com/p/71796835 https://mp.weixin.qq.com/s/Cd4uRslnek8r_a6chjwnYQ https://www.jianshu.com/p/61044808321f
- Java保留两位小数 and 浮点数精确计算 and BigDecimal介绍
- java练习 计算n位可被浮点数精确表示的小数
- 关于数据库中浮点运算、保留小数和时间计算
- 无穷分数 无穷的分数,有时会趋向于固定的数字。 请计算【图1.jpg】所示的无穷分数,要求四舍五入,精确到小数点后5位,小数位不足的补0。 请填写该浮点数,不能填写任何多余的内容。
- 浅谈iOS 关于小数精确计算(NSDecimalNumber)
- 由atof发现的C中浮点小数不精确问题
- 关于BigDecimal 的不精确计算问题
- 小数精确计算
- 解决javascript中的浮点数计算不精确问题
- 总结群里讨论的关于浮点数,如何四舍五入保留两位小数的处理方式
- 在Java中实现浮点数的精确计算
- java精度计算代码,指定精确小数位
- 关于浮点数计算时的精度问题
- 简单解决 Javascrip 浮点数计算的 Bug(.toFixed(int 小数位数))
- 【JS】527- 关于 JS 中的浮点计算
- javascript关于小数计算的结果会出现小数的位数变多的现象
- Javascript中小数精确计算问题
- 关于数据精确计算,以及四舍五入中,你所不知道的坑
- js浮点数精确计算(加、减、乘、除)
- 关于多线程下载时计算数据块大小、下载起始位置、结束位置的理解