1. 程式人生 > >深入學習java原始碼之Math.floor()與 Math.rint()

深入學習java原始碼之Math.floor()與 Math.rint()

深入學習java原始碼之Math.floor()與 Math.rint()

java中有三種移位運算子

 

<<      :     左移運算子,num << 1,相當於num乘以2

>>      :     右移運算子,num >> 1,相當於num除以2

>>>    :     無符號右移,忽略符號位,空位都以0補齊
 

二進位制最左端的數字為符號位,0代表正,1代表負,這裡先介紹幾個概念

邏輯左移=算術左移:高位溢位,低位補0 
邏輯右移:低位溢位,高位補0 
算術右移:低位溢位,高位用符號位的值補

比如一個有符號位的8位二進位制數10101010,[]是新增的數字

邏輯左移一位:0101010[0] 
邏輯左移兩位:101010[00]

算術左移一位:0101010[0] 
算術左移兩位:101010[00]

邏輯右移一位:[0]1010101 
邏輯右移兩位:[00]101010

算術右移一位:[1]1010101 
算術右移兩位:[11]101010

算術左移和算術右移主要用來進行有符號數的倍增、減半 
邏輯左移和邏輯右移主要用來進行無符號數的倍增、減半 
(Java中是沒有無符號資料型別的,C和C++中有)

 

java中的邏輯運算子

Java中&叫做按位與,&&叫做短路與,它們的區別是:
& 既是位運算子又是邏輯運算子,&的兩側可以是int,也可以是boolean表示式,當&兩側是int時,要先把運算子兩側的數轉化為二進位制數再進行運算,而短路與(&&)的兩側要求必須是布林表示式。

12&5 的值是多少?答:12轉成二進位制數是1100(前四位省略了),5轉成二進位制數是0101,則運算後的結果為0100即4 這是兩側為數值時;

若 int i = 2,j = 4;則(++i=2)&(j++=4)的結果為false,其過程是這樣的:先判斷++i=2是否成立,這裡當然是不成立了(3 == 2),但是程式還會繼續判斷下一個表示式是否成立,j++=4 ,該表示式是成立的,但是&運算子要求運算子兩側的值都為真,結果才為真,所以(++i=2)&(j++=4)的結果為 false 注意 :&為真的條件是兩側表示式都為真,但是即使我們判斷出左側表示式的值為false,程式也還是要繼續執行去判斷右側的表示式值的真假
若 int i = 2,j = 4;則(++i=2)&&(j++=4)的結果為false,其過程基本上和上面的是相同的,但是若左側表示式的值為false時,程式則不會繼續判斷右側表示式的真假了,短路與中,短路這個詞大概也就是這個意思吧


Java中‘|’與‘||’的區別

int i=0;
if(3>2 || (i++)>1) i=i+1;
System.out.println(i);

這段程式會打印出1,而不是打印出2。
因為在if的條件判斷中,程式先判斷第一個表示式3>2是否成立,結果3>2為真,那麼按照邏輯來說,無論後面一個表示式(i++)>1是否成立,整個或表示式肯定為真,因此程式就不去執行判斷後面一個表示式即(i++)>1了,所以這裡i並沒有自增1。然後程式執行到i=i+1,於是i變為1。最後打印出1。

int i=0;
if(3>2 | (i++)>1) i=i+1;
System.out.println(i);

如果換做這樣寫,那麼就是打印出2了,因為無論第一個條件3>2是否為真,程式都會去執行判斷第二個條件表示式,因此i++這個自增是會被執行的,再加上if內的i=i+1,所以最終i=2。

Modifier and Type Method and Description
static double abs(double a)

返回值為 double絕對值。

static float abs(float a)

返回 float值的絕對值。

static int abs(int a)

返回值為 int絕對值。

static long abs(long a)

返回值為 long絕對值。

static double ceil(double a)

返回大於或等於引數的最小(最接近負無窮大) double值,等於一個數學整數。

static double copySign(double magnitude, double sign)

使用第二個浮點引數的符號返回第一個浮點引數。

static float copySign(float magnitude, float sign)

使用第二個浮點引數的符號返回第一個浮點引數。

static double floor(double a)

返回小於或等於引數的最大(最接近正無窮大) double值,等於一個數學整數。

static int getExponent(double d)

返回a的表示中使用的無偏指數 double

static int getExponent(float f)

返回a的表示中使用的無偏指數 float

static double rint(double a)

返回與引數最接近值的 double值,並且等於數學整數。

 

java原始碼

public final class Math {

    private Math() {}

    public static double ceil(double a) {
        return StrictMath.ceil(a); // default impl. delegates to StrictMath
    }

    public static double floor(double a) {
        return StrictMath.floor(a); // default impl. delegates to StrictMath
    }

    public static double rint(double a) {
        return StrictMath.rint(a); // default impl. delegates to StrictMath
    }

    public static int getExponent(float f) {
        /*
         * Bitwise convert f to integer, mask out exponent bits, shift
         * to the right and then subtract out float's bias adjust to
         * get true exponent value
         */
        return ((Float.floatToRawIntBits(f) & FloatConsts.EXP_BIT_MASK) >>
                (FloatConsts.SIGNIFICAND_WIDTH - 1)) - FloatConsts.EXP_BIAS;
    }

    public static double copySign(double magnitude, double sign) {
        return Double.longBitsToDouble((Double.doubleToRawLongBits(sign) &
                                        (DoubleConsts.SIGN_BIT_MASK)) |
                                       (Double.doubleToRawLongBits(magnitude) &
                                        (DoubleConsts.EXP_BIT_MASK |
                                         DoubleConsts.SIGNIF_BIT_MASK)));
    }	

    public static float copySign(float magnitude, float sign) {
        return Float.intBitsToFloat((Float.floatToRawIntBits(sign) &
                                     (FloatConsts.SIGN_BIT_MASK)) |
                                    (Float.floatToRawIntBits(magnitude) &
                                     (FloatConsts.EXP_BIT_MASK |
                                      FloatConsts.SIGNIF_BIT_MASK)));
    }


    public static int abs(int a) {
        return (a < 0) ? -a : a;
    }

    public static long abs(long a) {
        return (a < 0) ? -a : a;
    }

    public static float abs(float a) {
        return (a <= 0.0F) ? 0.0F - a : a;
    }

    public static double abs(double a) {
        return (a <= 0.0D) ? 0.0D - a : a;
    }

}	

 

public final class StrictMath {

    private StrictMath() {}

    public static double ceil(double a) {
        return floorOrCeil(a, -0.0, 1.0, 1.0);
    }
	
    public static double floor(double a) {
        return floorOrCeil(a, -1.0, 0.0, -1.0);
    }	

    private static double floorOrCeil(double a,
                                      double negativeBoundary,
                                      double positiveBoundary,
                                      double sign) {
        int exponent = Math.getExponent(a);

        if (exponent < 0) {
            /*
             * Absolute value of argument is less than 1.
             * floorOrceil(-0.0) => -0.0
             * floorOrceil(+0.0) => +0.0
             */
            return ((a == 0.0) ? a :
                    ( (a < 0.0) ?  negativeBoundary : positiveBoundary) );
        } else if (exponent >= 52) {
            /*
             * Infinity, NaN, or a value so large it must be integral.
             */
            return a;
        }
        // Else the argument is either an integral value already XOR it
        // has to be rounded to one.
        assert exponent >= 0 && exponent <= 51;

        long doppel = Double.doubleToRawLongBits(a);
        long mask   = DoubleConsts.SIGNIF_BIT_MASK >> exponent;

        if ( (mask & doppel) == 0L )
            return a; // integral value
        else {
            double result = Double.longBitsToDouble(doppel & (~mask));
            if (sign*a > 0.0)
                result = result + sign;
            return result;
        }
    }
	
    public static double rint(double a) {
        double twoToThe52 = (double)(1L << 52); // 2^52
        double sign = Math.copySign(1.0, a); // preserve sign info
        a = Math.abs(a);

        if (a < twoToThe52) { // E_min <= ilogb(a) <= 51
            a = ((twoToThe52 + a ) - twoToThe52);
        }

        return sign * a; // restore original sign
    }	
	
    public static double copySign(double magnitude, double sign) {
        return Math.copySign(magnitude, (Double.isNaN(sign)?1.0d:sign));
    }

    public static float copySign(float magnitude, float sign) {
        return Math.copySign(magnitude, (Float.isNaN(sign)?1.0f:sign));
    }	
}