欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java学习笔记:关于Java double类型相加问题

程序员文章站 2022-03-13 15:56:23
目录java double类型相加问题一、这个时候就要采用bigdecimal函数进行运算二、double 三种加法比较java double类详解double 类的构造方法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相加出现的怪事
急需的话,直接学习、创建该工具类,就可以完成项目了。以下是 加法算法的几个实现的方法。

new bigdecimal(double.tostring(double)).add(new bigdecimal(double.tostring(double));
    /**
     * @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);
    }

    /**
     * @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);
    }
    /**
     * @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 算法对操作数预期的结果,以单精度和双精度格式表示。

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位机器结果都一样。 对于精度计算结果影响不大。

附录:.

//使用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 对象:

double double1 = new double(5.556);    // 以 double 类型的变量作为参数创建 double 对象
double double2 = new double("5.486");       // 以 string 类型的变量作为参数创建 double 对象

double 类的常用方法

Java学习笔记:关于Java double类型相加问题

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

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 实例。

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