您当前的位置: 首页 >  Java

wespten

暂无认证

  • 0浏览

    0关注

    899博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

深入学习java源码之Double.parseDouble()与Double.valueOf()

wespten 发布时间:2019-01-13 07:42:05 ,浏览量:0

深入学习java源码之Double.parseDouble()与Double.valueOf() 

Double类是原始类型double的包装类,它包含若干有效处理double值的方法,如将其转换为字符串表示形式,反之亦然。Double类的对象可以包含一个double值。

public class Double_test
{
 
    public static void main(String[] args)
    {
        
        double b = 55.05;
        String bb = "45";
 
        // Construct two Double objects
        Double x = new Double(b);
        Double y = new Double(bb);
 
        // toString()
        System.out.println("toString(b) = " + Double.toString(b));
 
        // valueOf()
        // return Double object
        Double z = Double.valueOf(b);
        System.out.println("valueOf(b) = " + z);
        z = Double.valueOf(bb);
        System.out.println("ValueOf(bb) = " + z);
 
        // parseDouble()
        // return primitive double value
        double zz = Double.parseDouble(bb);
        System.out.println("parseDouble(bb) = " + zz);
 
        System.out.println("bytevalue(x) = " + x.byteValue());
        System.out.println("shortvalue(x) = " + x.shortValue());
        System.out.println("intvalue(x) = " + x.intValue());
        System.out.println("longvalue(x) = " + x.longValue());
        System.out.println("doublevalue(x) = " + x.doubleValue());
        System.out.println("floatvalue(x) = " + x.floatValue());
 
        int hash = x.hashCode();
        System.out.println("hashcode(x) = " + hash);
 
        boolean eq = x.equals(y);
        System.out.println("x.equals(y) = " + eq);
 
        int e = Double.compare(x, y);
        System.out.println("compare(x,y) = " + e);
 
        int f = x.compareTo(y);
        System.out.println("x.compareTo(y) = " + f);
 
        Double d = Double.valueOf("1010.54789654123654");
        System.out.println("isNaN(d) = " + d.isNaN());
 
        System.out.println("Double.isNaN(45.12452) = " + Double.isNaN(45.12452));
 
        // Double.POSITIVE_INFINITY stores
        // the positive infinite value
        d = Double.valueOf(Double.POSITIVE_INFINITY + 1);
        System.out.println("Double.isInfinite(d) = " + 
                                    Double.isInfinite(d.doubleValue()));
 
        double dd = 10245.21452;
        System.out.println("Double.toString(dd) = " + Double.toHexString(dd));
 
        long double_to_long = Double.doubleToLongBits(dd);
        System.out.println("Double.doubleToLongBits(dd) = " + double_to_long);
 
        double long_to_double = Double.longBitsToDouble(double_to_long);
        System.out.println("Double.LongBitsToDouble(double_to_long) = " + 
                                    long_to_double);
    }
 
}

输出:

toString(b) = 55.05
valueOf(b) = 55.05
ValueOf(bb) = 45.0
parseDouble(bb) = 45.0
bytevalue(x) = 55
shortvalue(x) = 55
intvalue(x) = 55
longvalue(x) = 55
doublevalue(x) = 55.05
floatvalue(x) = 55.05
hashcode(x) = 640540672
x.equals(y) = false
compare(x,y) = 1
x.compareTo(y) = 1
isNaN(d) = false
Double.isNaN(45.12452) = false
Double.isInfinite(d) = true
Double.toString(dd) = 0x1.4029b7564302bp13
Double.doubleToLongBits(dd) = 4666857980575363115
Double.LongBitsToDouble(double_to_long) = 10245.21452

 

Double类型的计算

如果我们编译运行下面这个程序会看到什么?

public class Test{
    public static void main(String args[]){
        System.out.println(0.05+0.01);
        System.out.println(1.0-0.42);
        System.out.println(4.015*100);
        System.out.println(123.3/100);
    }
};

你没有看错!结果确实是

0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999

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

public double round(double value){
    return Math.round(value*100)/100.0;
}

非常不幸,上面的代码并不能正常工作,给这个方法传入4.015它将返回4.01而不是4.02,如我们在上面看到的 4.015*100=401.49999999999994 因此如果我们要做到精确的四舍五入,不能利用简单类型做任何运算 java.text.DecimalFormat也不能解决这个问题:

System.out.println(new java.text.DecimalFormat("0.00").format(4.025));

输出是4.02

精确计算

float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用 java.math.BigDecimal

我们如果需要精确计算,非要用String来够造BigDecimal不可!

divide方法中推荐使用枚举RoundingMode.HALF_UP

 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 /**
  * double的计算不精确,会有类似0.0000000000000002的误差,正确的方法是使用BigDecimal或者用整型
  * 整型地方法适合于货币精度已知的情况,比如12.11+1.10转成1211+110计算,最后再/100即可
  * 以下是摘抄的BigDecimal方法:
  */
 public class DoubleUtil implements Serializable {
     private static final long serialVersionUID = -3345205828566485102L;
     // 默认除法运算精度
     private static final Integer DEF_DIV_SCALE = 2;
 
     /**
      * 提供精确的加法运算。
      *
      * @param value1 被加数
      * @param value2 加数
      * @return 两个参数的和
      */
     public static Double add(Double value1, Double value2) {
         BigDecimal b1 = new BigDecimal(Double.toString(value1));
         BigDecimal b2 = new BigDecimal(Double.toString(value2));
         return b1.add(b2).doubleValue();
     }
 
     /**
      * 提供精确的减法运算。
      *
      * @param value1 被减数
      * @param value2 减数
      * @return 两个参数的差
      */
     public static double sub(Double value1, Double value2) {
         BigDecimal b1 = new BigDecimal(Double.toString(value1));
         BigDecimal b2 = new BigDecimal(Double.toString(value2));
         return b1.subtract(b2).doubleValue();
     }
 
     /**
      * 提供精确的乘法运算。
      *
      * @param value1 被乘数
      * @param value2 乘数
      * @return 两个参数的积
      */
     public static Double mul(Double value1, Double value2) {
         BigDecimal b1 = new BigDecimal(Double.toString(value1));
         BigDecimal b2 = new BigDecimal(Double.toString(value2));
         return b1.multiply(b2).doubleValue();
     }
 
     /**
      * 提供(相对)精确的除法运算,当发生除不尽的情况时, 精确到小数点以后10位,以后的数字四舍五入。
      *
      * @param dividend 被除数
      * @param divisor  除数
      * @return 两个参数的商
      */
     public static Double divide(Double dividend, Double divisor) {
         return divide(dividend, divisor, DEF_DIV_SCALE);
     }
 
     /**
      * 提供(相对)精确的除法运算。 当发生除不尽的情况时,由scale参数指定精度,以后的数字四舍五入。
      *
      * @param dividend 被除数
      * @param divisor  除数
      * @param scale    表示表示需要精确到小数点以后几位。
      * @return 两个参数的商
      */
     public static Double divide(Double dividend, Double divisor, Integer scale) {
         if (scale < 0) {
             throw new IllegalArgumentException("The scale must be a positive integer or zero");
         }
         BigDecimal b1 = new BigDecimal(Double.toString(dividend));
         BigDecimal b2 = new BigDecimal(Double.toString(divisor));
         return b1.divide(b2, scale,RoundingMode.HALF_UP).doubleValue();
     }
 
     /**
      * 提供指定数值的(精确)小数位四舍五入处理。
      *
      * @param value 需要四舍五入的数字
      * @param scale 小数点后保留几位
      * @return 四舍五入后的结果
      */
     public static double round(double value,int scale){
         if(scale> 32));
    }	
	
    public boolean equals(Object obj) {
        return (obj instanceof Double)
               && (doubleToLongBits(((Double)obj).value) ==
                      doubleToLongBits(value));
    }	
	
    public static long doubleToLongBits(double value) {
        long result = doubleToRawLongBits(value);
        // Check for NaN based on values of bit fields, maximum
        // exponent and nonzero significand.
        if ( ((result & DoubleConsts.EXP_BIT_MASK) ==
              DoubleConsts.EXP_BIT_MASK) &&
             (result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)
            result = 0x7ff8000000000000L;
        return result;
    }	
	
    public static native long doubleToRawLongBits(double value);	
	
    public static native double longBitsToDouble(long bits);	
	
    public int compareTo(Double anotherDouble) {
        return Double.compare(value, anotherDouble.value);
    }
	
    public static int compare(double d1, double d2) {
        if (d1 < d2)
            return -1;           // Neither val is NaN, thisVal is smaller
        if (d1 > d2)
            return 1;            // Neither val is NaN, thisVal is larger

        // Cannot use doubleToRawLongBits because of possibility of NaNs.
        long thisBits    = Double.doubleToLongBits(d1);
        long anotherBits = Double.doubleToLongBits(d2);

        return (thisBits == anotherBits ?  0 : // Values are equal
                (thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
                 1));                          // (0.0, -0.0) or (NaN, !NaN)
    }	
	
    public static double sum(double a, double b) {
        return a + b;
    }	
	
    public static double max(double a, double b) {
        return Math.max(a, b);
    }	

    public static double min(double a, double b) {
        return Math.min(a, b);
    }
	
    private static final long serialVersionUID = -9172774392245257468L;
}	
package java.lang;
import java.util.*;

public interface Comparable {
    public int compareTo(T o);
}
package java.lang;

public abstract class Number implements java.io.Serializable {

    public abstract int intValue();

    public abstract long longValue();

    public abstract float floatValue();

    public abstract double doubleValue();

    public byte byteValue() {
        return (byte)intValue();
    }

    public short shortValue() {
        return (short)intValue();
    }
	
    private static final long serialVersionUID = -8742448824652078965L;
}

 

关注
打赏
1665965058
查看更多评论
立即登录/注册

微信扫码登录

0.4720s