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

深入学习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<0){
             throw new IllegalArgumentException("The scale must be a positive integer or zero");
         }
         BigDecimal b = new BigDecimal(Double.toString(value));
         BigDecimal one = new BigDecimal("1");
         return b.divide(one,scale, RoundingMode.HALF_UP).doubleValue();
     }
 }

 

 

Modifier and Type Method and Description
byte byteValue()

返回此值 Doublebyte的基本收缩转换后。

static int compare(double d1, double d2)

比较两个指定的 double值。

int compareTo(Double anotherDouble)

数字比较两个 Double对象。

static long doubleToLongBits(double value)

根据IEEE 754浮点“双格式”位布局返回指定浮点值的表示。

static long doubleToRawLongBits(double value)

根据IEEE 754浮点“双格式”位布局返回指定浮点值的表示,保留非数字(NaN)值。

double doubleValue()

返回此 Double对象的 double值。

boolean equals(Object obj)

将此对象与指定对象进行比较。

float floatValue()

返回此值 Doublefloat的基本收缩转换后。

int hashCode()

返回此 Double对象的哈希码。

static int hashCode(double value)

返回一个double值的哈希码; 兼容Double.hashCode()

int intValue()

int后,返回 Double作为int的值。

static boolean isFinite(double d)

如果参数是有限浮点值,则返回true ; 返回false (对于NaN和无穷大参数)。

boolean isInfinite()

返回 true如果这 Double值是无限大, false其他。

static boolean isInfinite(double v)

返回 true如果指定的数量是无限大, false其他。

boolean isNaN()

如果 DoubleDouble数字(NaN),则返回 truefalse false。

static boolean isNaN(double v)

如果指定的数字是非数字(NaN)值,则返回 truefalse false。

static double longBitsToDouble(long bits)

返回与给 double表示相对应的 double值。

long longValue()

返回此值 Doublelong的基本收缩转换后。

static double max(double a, double b)

返回两个 double值中的较大值,就像调用 Math.max一样 。

static double min(double a, double b)

返回两个 double的较小值,就像调用 Math.min一样 。

static double parseDouble(String s)

返回一个新 double初始化为指定的代表的值 String ,如通过执行 valueOf类的方法 Double

short shortValue()

返回此值 Doubleshort的基本收缩转换后。

static double sum(double a, double b)

按照+运算符将两个 double值一起添加。

static String toHexString(double d)

返回 double参数的十六进制字符串 double形式。

String toString()

返回此 Double对象的字符串表示形式。

static String toString(double d)

返回 double参数的字符串 double形式。

static Double valueOf(double d)

返回一个 Double double值的 Double实例。

static Double valueOf(String s)

返回一个 Double对象,保存由参数字符串 sdouble值。

java源码

package java.lang;

import sun.misc.FloatingDecimal;
import sun.misc.FpUtils;
import sun.misc.DoubleConsts;

public final class Double extends Number implements Comparable {

    public static final double POSITIVE_INFINITY = 1.0 / 0.0;

    public static final double NEGATIVE_INFINITY = -1.0 / 0.0;

    public static final double NaN = 0.0d / 0.0;

    public static final double MAX_VALUE = 0x1.fffffffffffffP+1023; // 1.7976931348623157e+308

    public static final double MIN_NORMAL = 0x1.0p-1022; // 2.2250738585072014E-308

    public static final double MIN_VALUE = 0x0.0000000000001P-1022; // 4.9e-324

    public static final int MAX_EXPONENT = 1023;

    public static final int MIN_EXPONENT = -1022;

    public static final int SIZE = 64;

    public static final int BYTES = SIZE / Byte.SIZE;

    @SuppressWarnings("unchecked")
    public static final Class   TYPE = (Class) Class.getPrimitiveClass("double");

    public static String toString(double d) {
        return FloatingDecimal.toJavaFormatString(d);
    }

    public static String toHexString(double d) {
        /*
         * Modeled after the "a" conversion specifier in C99, section
         * 7.19.6.1; however, the output of this method is more
         * tightly specified.
         */
        if (!isFinite(d) )
            // For infinity and NaN, use the decimal output.
            return Double.toString(d);
        else {
            // Initialized to maximum size of output.
            StringBuilder answer = new StringBuilder(24);

            if (Math.copySign(1.0, d) == -1.0)    // value is negative,
                answer.append("-");                  // so append sign info

            answer.append("0x");

            d = Math.abs(d);

            if(d == 0.0) {
                answer.append("0.0p0");
            } else {
                boolean subnormal = (d < DoubleConsts.MIN_NORMAL);

                // Isolate significand bits and OR in a high-order bit
                // so that the string representation has a known
                // length.
                long signifBits = (Double.doubleToLongBits(d)
                                   & DoubleConsts.SIGNIF_BIT_MASK) |
                    0x1000000000000000L;

                // Subnormal values have a 0 implicit bit; normal
                // values have a 1 implicit bit.
                answer.append(subnormal ? "0." : "1.");

                // Isolate the low-order 13 digits of the hex
                // representation.  If all the digits are zero,
                // replace with a single 0; otherwise, remove all
                // trailing zeros.
                String signif = Long.toHexString(signifBits).substring(3,16);
                answer.append(signif.equals("0000000000000") ? // 13 zeros
                              "0":
                              signif.replaceFirst("0{1,12}$", ""));

                answer.append('p');
                // If the value is subnormal, use the E_min exponent
                // value for double; otherwise, extract and report d's
                // exponent (the representation of a subnormal uses
                // E_min -1).
                answer.append(subnormal ?
                              DoubleConsts.MIN_EXPONENT:
                              Math.getExponent(d));
            }
            return answer.toString();
        }
    }

    public static Double valueOf(String s) throws NumberFormatException {
        return new Double(parseDouble(s));
    }

    public static Double valueOf(double d) {
        return new Double(d);
    }
	
    public static double parseDouble(String s) throws NumberFormatException {
        return FloatingDecimal.parseDouble(s);
    }	
	
    public static boolean isNaN(double v) {
        return (v != v);
    }
	
    public static boolean isInfinite(double v) {
        return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);
    }	
	
    public static boolean isFinite(double d) {
        return Math.abs(d) <= DoubleConsts.MAX_VALUE;
    }	
	
    private final double value;	
	
    public Double(double value) {
        this.value = value;
    }	
	
    public Double(String s) throws NumberFormatException {
        value = parseDouble(s);
    }	
	
    public boolean isNaN() {
        return isNaN(value);
    }	
	
    public boolean isInfinite() {
        return isInfinite(value);
    }	
	
    public String toString() {
        return toString(value);
    }
	
    public byte byteValue() {
        return (byte)value;
    }	
	
    public short shortValue() {
        return (short)value;
    }	
	
    public int intValue() {
        return (int)value;
    }	
	
    public long longValue() {
        return (long)value;
    }	
	
    public float floatValue() {
        return (float)value;
    }	
	
    public double doubleValue() {
        return value;
    }	
	
    @Override
    public int hashCode() {
        return Double.hashCode(value);
    }	
	
    public static int hashCode(double value) {
        long bits = doubleToLongBits(value);
        return (int)(bits ^ (bits >>> 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;
}

 

你可能感兴趣的:(Java源码)