我是靠谱客的博主 含蓄钢笔,这篇文章主要介绍Java学习笔记:关于Java double类型相加问题,现在分享给大家,希望可以做个参考。

Java double类型相加问题

多个double类型的数直接相加的时候,可能存在精度误差.( 由于计算机算法以及硬件环境决定只能识别 0 1。计算机默认的计算结果在都在一个指定精度范围之内,想往深的了解,可以学习数值分析等)

在金融方面是绝对不允许的,好在java开发者有这个先见之明。

java.math.*里面提供了BigDecimal类(提供高精度计算的方法)

一、这个时候就要采用BigDecimal函数进行运算

第一步、建立String类型的数据

第二步、创建BigDecimal对象BigDecimal(Double.toString(double))

以下两种不推荐:

BigDecimal(double)或者BigDecimal(Double.valueOf(double)))

建议: 涉及到精度问题的时候,整个计算过程都是用String类型或者BigDecimal类对象。最后结果根据需求 在转过来。

另外该文章提供了一个计算辅助类Java Double相加出现的怪事

急需的话,直接学习、创建该工具类,就可以完成项目了。以下是 加法算法的几个实现的方法。

复制代码
1
new BigDecimal(Double.toString(double)).add(new BigDecimal(Double.toString(double));
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
/** * @param b1 * BigDecimal * @param v2 * double * @return BigDecimal * */ public BigDecimal add(BigDecimal b1, double v2) { // BigDecimal b1=new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.add(b2); }

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
/** * @param b1 * double * @param v2 * double * @return BigDecimal * */ public BigDecimal add(double v1, double v2) { BigDecimal b1=new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.add(b2); }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
/** * @param b1 * double * @param v2 * double * @return double * */ public double add(double v1, double v2) { BigDecimal b1=new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.add(b2).doubleValue(); }

二、double 三种加法比较

+,strictfp,BigDecimel

Strictfp —— Java 关键字。

可应用于类、接口或方法。

使用 strictfp 关键字声明一个方法时,该方法中所有的float和double表达式都严格遵守FP-strict的限制,符合IEEE-754规范。

严格约束意味着所有表达式的结果都必须是 IEEE 754 算法对操作数预期的结果,以单精度和双精度格式表示。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class MathDemo { /** * @param args */ public static void main(String[] args) { System.err.println("普通 "+ addNormal(12353.21,21334.24,154435.03)); System.err.println("strictfp "+addDouble(12353.21,21334.24,154435.03)); System.err.println("BigDEcimel: "+add(12353.21,21334.24,154435.03)); } public static double addNormal(double... v1) { double res = 0; for (int i = 0; i < v1.length; i++) { res += v1[i]; } return res; } public static strictfp double addDouble(double... v) { double res = 0; for (int i = 0; i < v.length; i++) { res += v[i]; } return res; } /** * @param b1 * double * @param v2 * double * @return double */ public static double add(double... v) { BigDecimal b = new BigDecimal(Double.toString(v[0])); for (int i = 1; i < v.length; i++) { BigDecimal b2 = new BigDecimal(Double.toString(v[i])); b=b.add(b2); } return b.doubleValue(); } }

输入
12353.21,21334.24,154435.03三个类型的数据时候
结果:
普通 188122.47999999998
strictfp 188122.47999999998
BigDEcimel: 188122.48

输入
3.21, 4.24,5.03
结果
普通 12.48
strictfp 12.48
BigDEcimel: 12.48

输入:
12353.21,21334.24
结果:
普通 33687.45
strictfp 33687.45
BigDEcimel: 33687.45

结论是:

BigDecimal的算法精度比较好。 其余两种方法 都存在缺点。至于strictfp 这个关键字 是去平台化影响。比如32为机器和64位机器结果都一样。 对于精度计算结果影响不大。

附录:.

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//使用double类型创建BigDecimal public BigDecimal(double val) { if (Double.isInfinite(val) || Double.isNaN(val)) throw new NumberFormatException("Infinite or NaN"); // Translate the double into sign, exponent and significand, according // to the formulae in JLS, Section 20.10.22. long valBits = Double.doubleToLongBits(val); int sign = ((valBits >> 63)==0 ? 1 : -1); int exponent = (int) ((valBits >> 52) & 0x7ffL); long significand = (exponent==0 ? (valBits & ((1L<<52) - 1)) << 1 : (valBits & ((1L<<52) - 1)) | (1L<<52)); exponent -= 1075; // At this point, val == sign * significand * 2**exponent. /* * Special case zero to supress nonterminating normalization * and bogus scale calculation. */ if (significand == 0) { intVal = BigInteger.ZERO; intCompact = 0; precision = 1; return; } // Normalize while((significand & 1) == 0) { // i.e., significand is even significand >>= 1; exponent++; } // Calculate intVal and scale long s = sign * significand; BigInteger b; if (exponent < 0) { b = BigInteger.valueOf(5).pow(-exponent).multiply(s); scale = -exponent; } else if (exponent > 0) { b = BigInteger.valueOf(2).pow(exponent).multiply(s); } else { b = BigInteger.valueOf(s); } intCompact = compactValFor(b); intVal = (intCompact != INFLATED) ? null : b; }

Java double类详解

Double 类的构造方法

Double 类中的构造方法有如下两个。

  • Double(double value):构造一个新分配的 Double 对象,它表示转换为 double 类型的参数。
  • Double(String s):构造一个新分配的 Double 对象,它表示 String 参数所指示的 double 值。

分别使用以上两个构造方法获取 Double 对象:

复制代码
1
2
Double double1 = new Double(5.556); // 以 double 类型的变量作为参数创建 Double 对象 Double double2 = new Double("5.486"); // 以 String 类型的变量作为参数创建 Double 对象

Double 类的常用方法

如何将字符串 56.7809 转换为 double 类型的数值,或者将 double 类型的数值 56.7809 转换为对应的字符串呢?

复制代码
1
2
3
4
String str = "56.7809"; double num = Double.parseDouble(str); // 将字符串转换为 double 类型的数值 double d = 56.7809; String s = Double.toString(d); // 将double类型的数值转换为字符串

在将字符串转换为 double 类型的数值的过程中,如果字符串中包含非数值类型的字符,则程序执行将出现异常。

Double 类的常用常量

在 Double 类中包含了很多常量,其中较为常用的常量如下。

  • MAX_VALUE:值为 1.8E308 的常量,它表示 double 类型的最大正有限值的常量。
  • MIN_VALUE:值为 4.9E-324 的常量,它表示 double 类型数据能够保持的最小正非零值的常量。
  • NaN:保存 double 类型的非数字值的常量。
  • NEGATIVE_INFINITY:保持 double 类型的负无穷大的常量。
  • POSITIVE_INFINITY:保持 double 类型的正无穷大的常量。
  • SIZE:用秦以二进制补码形式表示 double 值的比特位数。
  • TYPE:表示基本类型 double 的 Class 实例。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持靠谱客。

最后

以上就是含蓄钢笔最近收集整理的关于Java学习笔记:关于Java double类型相加问题的全部内容,更多相关Java学习笔记内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(145)

评论列表共有 0 条评论

立即
投稿
返回
顶部