java double 计算出错的问题

本文详细探讨了在Android应用开发中遇到的double数据类型计算不精确问题,介绍了导致此现象的原因,并提供了商业级Java浮点数精度计算的解决方案,包括精确的乘法、加法和减法运算,以及针对不同需求的金额乘法、加法和产品加法计算方法。

最近在做android上的商城应用 使用到 double 进行加减计算是出现 错误 时不时出现浮点数计算不精确的问题。

纠结好久,以为我所学到的加减乘除已经out了。。

下面这个错误:

398649.9+0.2 = 398650.10000000003

着实让我无语。

其实并不是我的用法有问题,而是对 double这种数据类型了解的不深而已,只停留在表面上的数字,没有去深究其构成。

http://tech.ccidnet.com/art/3737/20031021/455723_1.html

在网上找了一些资料 找到些比较好的解决方案,贴出来 备忘。。。

一下在网上搜索到整理比较完善的解决方法:

//商业用java浮点数精度计算

 /**

   * 提供精确的乘法运算

   * @param v1

   * @param v2

   * @param scale :保留精度,BigDecimal.ROUND_HALF_EVEN:财务常用的四舍六入五取偶,BigDecimal.ROUND_HALF_UP,包括>=.5就进位,比如3.455保留两位为3.46

   * @return 两个参数的积

   */

  public static double multiply(double v1, double v2,int scale)

  {

       return (BigDecimal.valueOf(v1).multiply(BigDecimal.valueOf(v2))).setScale(scale, BigDecimal.ROUND_HALF_EVEN).doubleValue();

   }

 

  /**

   * 提供精确的加法运算

   * @param v1

   * @param v2

   * @param scale :保留精度

   * @return 两个参数的和

   */

  public static double add(double v1, double v2,int scale)

  {

       return (BigDecimal.valueOf(v1).add(BigDecimal.valueOf(v2))).setScale(scale, BigDecimal.ROUND_HALF_EVEN).doubleValue();

  }

 

  /**

   * 提供精确的减法运算

   * @param v1

   * @param v2

   * @param scale :保留精度

   * @return 两个参数的差

   */

  public static double subtract(double v1, double v2,int scale)

  {

       return (BigDecimal.valueOf(v1).subtract(BigDecimal.valueOf(v2))).setScale(scale, BigDecimal.ROUND_HALF_EVEN).doubleValue();

  }

  /**提供金额乘法计算,用于金额与产品相乘,很少有连续相乘,所以只写一个

  * @param v1

  * @param v2

  * @return

  */

 public static double multiply(double v1,double v2)

 {

   return multiply(v1, v2, 2, BigDecimal.ROUND_HALF_UP);

 }

 

  /**提供金额加法计算,金额保留2位小数

  * @param v1

  * @param v2(可变参)

  * @return

  */

 public static double add(double v1,double... v2)

 {

  BigDecimal b1=BigDecimal.valueOf(v1);

  for (double d : v2) {

   b1=b1.add(BigDecimal.valueOf(d)).setScale(2, BigDecimal.ROUND_HALF_UP);

  }

  return b1.doubleValue();

 }

 

 /**提供产品加法计算,产品保留4位小数

  * @param v1

  * @param v2(可变参)

  * @return

  */

 public static double addProduct(double v1,double... v2)

 {

  BigDecimal b1=BigDecimal.valueOf(v1);

  for (double d : v2) {

   b1=b1.add(BigDecimal.valueOf(d)).setScale(4, BigDecimal.ROUND_HALF_UP);

  }

  return b1.doubleValue();

 }

<think>嗯,用户这次问的是Java中如何判断double类型的NaN。这个问题其实涉及到浮点数的特殊值处理,在数值计算中很重要。 用户提供的四个引用里,引用[1]讲double保留小数,引用[2]是String的equals方法,引用[3]提到字符串转double可能抛NumberFormatException,引用[4]讲强制类型转换。这些虽然都和double有关,但都没直接提到NaN的判断。 我记得JavaDouble类是有专门处理NaN的方法。NaN比较特殊,因为按照IEEE 754标准,NaN等于任何值,包括它自己。所以用户如果用==来判断,比如"if (x == Double.NaN)"肯定会出错,这个表达式永远返回false。 应该推荐用户使用Double.isNaN()这个静态方法,这是最标准的做法。另外Double.compare()方法也能处理NaN的比较,但用起来如isNaN简洁。还可以通过位模式判断,但太底层了,一般用到。 用户可能是遇到了浮点数计算异常,比如除零操作产生了NaN,现在需要检测这种情况。考虑到用户引用的内容都比较基础,回答要避免引入太多底层细节,重点讲清楚标准用法就好。 需要强调要用==判断NaN这个常见误区,这个坑很多新手都会踩。示例代码就写两行:一行展示错误做法,一行展示正确用法,对比鲜明些。 相关问题设计可以围绕NaN的特性和处理场景展开:为什么要这样设计,实际应用场景,以及相关的特殊值如无穷大怎么处理。这样能帮助用户建立系统认知。 </think>在Java中判断`double`类型的`NaN`(Not a Number)值,需使用**专门的方法**而非直接比较运算符。以下是三种可靠方法: ### 1. **推荐方案:`Double.isNaN()`方法** ```java double value = Math.sqrt(-1.0); // 产生NaN if (Double.isNaN(value)) { System.out.println("该值是NaN"); } ``` **原理**: `Double.isNaN()`是`Double`类的静态方法,内部通过位模式判断是否符合IEEE 754的NaN标准[^1]。 ### 2. 使用`Double.compare()`(适用于包含NaN的比较) ```java double a = Double.NaN; if (Double.compare(a, Double.NaN) == 0) { System.out.println("相等"); // 输出此行 } ``` **说明**: `Double.compare()`方法将两个NaN视为相等,而`==`运算符则行[^2],因为IEEE标准规定`NaN != NaN`。 ### 3. 手动位模式判断(极少用,仅作了解) ```java long bits = Double.doubleToLongBits(value); if ((bits & 0x7FF0000000000000L) == 0x7FF0000000000000L && (bits & 0x000FFFFFFFFFFFFFL) != 0L) { System.out.println("NaN"); } ``` ### ✅ 关键注意事项 **禁止用 `==` 判断NaN** ```java Double.NaN == Double.NaN; // 永远返回false! ``` 原因:IEEE 754标准规定NaN等于任何值(包括自身)[^1][^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值