**当你在写一个电商网站的时候,你可能会给你的商品标价1.99,10.9这样的价格来吸引顾客.我应该用浮点数float/double来储存它们,当我的顾客购买商品的时候,从他们的账户里扣费,使用整型是不可能的.你可能会这么想.

**如果你的顾客账号里的钱刚好是1950.00,5001.00这样的整元,那么恭喜你,你的想法是没有错的.但是一旦有一位顾客的账号里还有若干毛,若干分钱没花完,那你的程序就会得到一个错误的数值!很无奈的是,你无法通过报错信息找到它,如果你已经用浮点型float/double来计算,那么你将很难发现这个错误!

**例如,有这样一个业务需要处理:顾客有500.05块钱,你的商品定价19.9元.

        double d1 = 500.05;
double d2 = 19.9;
double d3 = d1 - d2;

**你可能想顾客钱包里应该还有480.15元.但是你得到的结果是480.15000000000003元.虽然相差很少,但是日积月累或者当你在经营一个亿万数据的网站,这将是个极大的BUG!

那么我们该怎么解决这个问题呢?

**如果你要解决某个问题,那么你首先要知道问题出现在哪.这是我写程序的准则那么问题出现在哪呢?经过百度+摸索,发现十进制数的二进制表示可能不够精确.浮点数值没办法用十进制来精确表示的原因要归咎于CPU表示浮点数的方法。这样的话您就可能会牺牲一些精度,有些浮点数运算也会引入误差。以上面提到的情况为例,480.15的二进制表示并非就是精确的480.15。反而最为接近的二进制表示是 480.15000000000003。原因在于浮点数由两部分组成:指数和尾数。

Java中的简单浮点数类型float和double不能够进行运算。不光是Java,在其它很多编程语言中也有这样的问题。在大多数情况下,计算的结果是准确的,但是多试几次(可以做一个循环)就可以试出类似上面的错误。现在终于理解为什么要有BCD码了。 这个问题相当严重,如果你有9.999999999999元,你的计算机是不会认为你可以购买10元的商品的。 在有的编程语言中提供了专门的货币类型来处理这种情况,但是Java没有。这个问题有两种方案.

1.你将得到的数经过放大n个整数倍后再除以n个整数倍.它的原理和java进制转换的原理相同.

2.不要用浮点数double/float进行计算,选择BigDecimal进行精确运算.

在使用BigDecimal类来进行计算的时候,主要分为以下步骤:

a、用float或者double变量构建BigDecimal对象。

b、通过调用BigDecimal的加,减,乘,除等相应的方法进行算术运算。

c、把BigDecimal对象转换成float,double,int等类型。

BigDecimal能够很好地对浮点数进行运算.但是他的计算过程相对来说十分麻烦,而且因为每次计算都要创建一个实例,十分消耗资源.以下举例说明它的计算过程

—->>>>

    BigDecimal b1 = new BigDecimal(Double.toString(500.05));
BigDecimal b2 = new BigDecimal(Double.toString(19.9));
System.out.println(b1.subtract(b2));
****要注意的是,如果你直接在BigDecimal b1 = new BigDecimal(Double.toString(500.05));里面写浮点数,依旧会出现精确度的偏差!

****最后,感谢同学魏勇/黎裕锦和我分享这个问题,如果后续有更加优秀的解决方案,我也会及时贴上来!**

有趣的Java之调皮的浮点数的更多相关文章

  1. java中float/double浮点数的计算失精度问题(转)

    如果我们编译运行下面这个程序会看到什么? public class Test  {    public static void main(String args[]) {                ...

  2. Java比较两个浮点数

    浮点数的基本数据类型不能用==比较,包装数据类型不能用 equals 比较 浮点数的表示 在计算机系统中,浮点数采用 符号+阶码+尾数 进行表示.在Java中,单精度浮点数float类型占32位,它的 ...

  3. 怒肝俩月,新鲜出炉史上最有趣的Java小白手册,第一版,每个 Java 初学者都应该收藏

    这么说吧,在我眼里,Java 就是最流行的编程语言,没有之一(PHP 往一边站).不仅岗位多,容易找到工作,关键是薪资水平也到位,不学 Java 亏得慌,对吧? 那可能零基础学编程的小伙伴就会头疼了, ...

  4. Java如何正确比较浮点数

    看下面这段代码,将 d1 和 d2 两个浮点数进行比较,输出的结果会是什么? double d1 = .1 * 3; double d2 = .3; System.out.println(d1 == ...

  5. 很有趣的Java分形绘制

    部分与整体以某种形式相似的形,称为分形. 首先我们举个例子:        我们可以看到西兰花一小簇是整个花簇的一个分支,而在不同尺度下它们具有自相似的外形.换句话说,较小的分支通过放大适当的比例后可 ...

  6. 记一个有趣的Java OOM!

    原文:https://my.oschina.net/u/1462914/blog/1630086 引言 熟悉Java的童鞋,应该对OOM比较熟悉.该类问题,一般都比较棘手.因为造成此类问题的原因有很多 ...

  7. 有趣的java小项目------猜拳游戏

    package com.aaa; //总结:猜拳游戏主要掌握3个方面:1.人出的动作是从键盘输入的(System.in)2.电脑是随机出的(Random随机数)3.双方都要出(条件判断) import ...

  8. Java正则表达式-匹配正负浮点数

    记录缘由: 公司项目需要从xml中获取标识为NUMBER的字符串,将之存入数据库中,存入的列的类型即为NUMBER.当遇到非数字时,原实现是通过异常: String plainValue = null ...

  9. 浮点数转换为人名币读法字符串(JAVA)

    /*<java疯狂讲义>浮点数转换为人名币读法字符串这个用例,感觉没有考虑零的情况*/ import java.util.Arrays; public class Num2Rmb { pr ...

随机推荐

  1. 前端读者 | 前端开发者调试面板vConsole

    来着微信团队开源的一个调试工具,[GitHub地址]https://github.com/Tencent/vConsole 一个轻量.可拓展.针对手机网页的前端开发者调试面板. 特性 查看 conso ...

  2. 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释

    P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...

  3. HDU 3339 In Action【最短路+01背包模板/主要是建模看谁是容量、价值】

     Since 1945, when the first nuclear bomb was exploded by the Manhattan Project team in the US, the n ...

  4. 2018 ACM-ICPC 青岛网络赛

    最近打比赛不知道为什么总是怀疑自己 写完之后不敢交,一定跟学长说一遍自己的思路 然后发现"哦原来我是对的" 然后就A掉了…… 所以还是要有自信 Problem A 最大值直接输出m ...

  5. 拜拜了,GOPATH君!新版本Golang的包管理入门教程

    Go 1.11和1.12实现了对包管理的初步支持,Go的新依赖管理系统使依赖版本信息明确且易于管理.Using Go Modules - The Go Blog 新的包管理模式有什么不同? 作为Go语 ...

  6. Spring MVC源码——Root WebApplicationContext

    目录 Spring MVC源码--Root WebApplicationContext 上下文层次结构 Root WebApplicationContext 初始化和销毁 ContextLoaderL ...

  7. UFO长啥样?--Python数据分析来告诉你

    前言 真心讲,长这么大,还没有见过UFO长啥样,偶然看到美国UFO报告中心有关于UFO时间记录的详细信息,突然想分析下这些记录里都包含了那些有趣的信息,于是有了这次的分析过程. 当然,原始数据包含的记 ...

  8. cpu亲和性绑定

    将进程与cpu绑定,最直观的好处就是减少cpu之间的cache同步和切换,提高了cpu cache的命中率,提高代码的效率.从cpu架构上,NUMA拥有独立的本地内存,节点之间可以通过互换模块做连接和 ...

  9. [NOIP 2004] T3 合并果子

    居然和BZOJ 1724完全一样o(╯□╰)o #include <bits/stdc++.h> using namespace std; typedef long long ll; in ...

  10. 找出最小元素的下标 Exercise07_10

    import java.util.Scanner; /** * @author 冰樱梦 * 时间:2018年下半年 * 题目:找出最小元素的下标 * */ public class Exercise0 ...