**当你在写一个电商网站的时候,你可能会给你的商品标价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. 洛谷——P1104 生日

    P1104 生日 题目描述 cjf君想调查学校OI组每个同学的生日,并按照从大到小的顺序排序.但cjf君最近作业很多,没有时间,所以请你帮她排序. 输入输出格式 输入格式: 有2行, 第1行为OI组总 ...

  2. PHP:根据二维数组中的某个字段进行排序

    首先了解下以下两个函数: 1.array_column() 返回输入数组中某个单一列的值. 2.array_multisort() 函数返回排序数组.您可以输入一个或多个数组.函数先对第一个数组进行排 ...

  3. Sd - Hibernate

    Sd - Hibernate 附:http://blog.csdn.net/ta8210/article/details/1582162 数据库连接池实现原理 http://hi.baidu.com/ ...

  4. 【数论】【欧拉函数】CDOJ1724 为了我们心爱的京电

    京州电子科技大学遭遇废校危机,为了保护我们心爱的学校,N位魔法少女站了出来,她们能做的就是……成为偶像! 每个魔法少女都拥有一定的人气,他们中的每个人的人气计算方式如下: 假设某个魔法少女的学号为a, ...

  5. 【贪心】POJ2376-Cleaning Shifts

    [题目大意] 给出几个小区间和大区间,求覆盖整个大区间的最少小区间个数,如果不可能则输出-1. [思路] 这道程序写得我很不爽快,迷迷糊糊写完了,提交一遍AC了,可是我自己都没怎么弄懂到底是怎么写出来 ...

  6. [转]XML中元素(Element)与节点(Node)的区别

    前言: element是特殊的node 一段纯文本即text-node也是node 但不是element w3c的原话是 A node can be an element node, an attri ...

  7. 通过Ollydbg定位私有协议通信明文

    简介:做安全的筒子经常会碰到这样的问题,当向要分析通信协议的时候往往都会有加密通信保护,对于SSL通信我们可以使用SSL劫持,但对于应用层面的加密就显得无能为力了,最好的办法就是调试应用,在应用内部去 ...

  8. 异常:System.BadImageFormatException,未能加载正确的程序集XXX或其某一依赖项

    常:System.BadImageFormatException,未能加载正确的程序集XXX或其某一依赖项 看到这个异常,我估计谁都会头大一阵子,不过还好,由于前面知道要设置为x86,加上以前观察过I ...

  9. 用C#写个邮件监控服务(一)

    监控服务,首先当然是个服务了.至于什么是windows服务,这里就不多说了.正题 1. 创建服务项目 打开VS编程环境,在C#中创建windows服务项目 2.创建后属性中更改名称和服务名. 3.增加 ...

  10. css/js(工作中遇到的问题)-6

    页面resize方法 if(document.createEvent) { const event = document.createEvent ("HTMLEvents"); e ...