Tuesday, September 16, 2014

JDK源碼分析&使用--Math.class篇(3)

內容預覽:
・copySign
・cos(回傳參數的餘弦值)
・cosh(返回一個雙曲餘弦值)
・decrementExact(返回遞減)
・exp(回傳以自然對數底)

copySign
螢幕快照 2014-07-05 下午09.31.22
螢幕快照 2014-07-05 下午09.33.30
注意:copySign不像StrictMath中的copySign方法
再看源碼:
螢幕快照 2014-07-05 下午09.46.03
這次沒有使用到StrictMath.class 喲,而是分別用了Double.class 和 Float.class 中的 longBitsToDouble 和intBitsToFloat方法,首先看看Double中的longBitsToDouble方法是啥的吧~
螢幕快照 2014-07-05 下午10.18.29
(返回對應於給定位表示形式的double 值)
看看它的源碼:
螢幕快照 2014-07-05 下午10.17.05
說明:
Returns the double value corresponding to a given bit representation. The argument is considered to be a representation of a floating-point value according to the IEEE 754 floating-point “double format" bit layout.
If the argument is 0x7ff0000000000000L, the result is positive infinity.
If the argument is 0xfff0000000000000L, the result is negative infinity.
If the argument is any value in the range 0x7ff0000000000001L through 0x7fffffffffffffffL or in the range0xfff0000000000001L through 0xffffffffffffffffL, the result is a NaN. No IEEE 754 floating-point operation provided by Java can distinguish between two NaN values of the same type with different bit patterns. Distinct values of NaN are only distinguishable by use of the Double.doubleToRawLongBits method.
In all other cases, let s, e, and m be three values that can be computed from the argument:
int s = ((bits >> 63) == 0) ? 1 : -1;
 int e = (int)((bits >> 52) & 0x7ffL);
 long m = (e == 0) ?
                 (bits & 0xfffffffffffffL) << 1 :
                 (bits & 0xfffffffffffffL) | 0x10000000000000L;
Then the floating-point result equals the value of the mathematical expression s·m·2e-1075.
Note that this method may not be able to return a double NaN with exactly same bit pattern as thelong argument. IEEE 754 distinguishes between two kinds of NaNs, quiet NaNs and signaling NaNs. The differences between the two kinds of NaN are generally not visible in Java. Arithmetic operations on signaling NaNs turn them into quiet NaNs with a different, but often similar, bit pattern. However, on some processors merely copying a signaling NaN also performs that conversion. In particular, copying a signaling NaN to return it to the calling method may perform this conversion. So longBitsToDoublemay not be able to return a double with a signaling NaN bit pattern. Consequently, for some longvalues, doubleToRawLongBits(longBitsToDouble(start)) may not equal start. Moreover, which particular bit patterns represent signaling NaNs is platform dependent; although all NaN bit patterns, quiet or signaling, must be in the NaN range identified above.
呵呵,一大堆英文⋯⋯
中文:
返回對應於給定的位表示的double值。該參數被認為是根據IEEE754浮點“雙精度格式”位佈局的浮點值的表示形式。
如果參數為0x7ff0000000000000L,結果為正無窮大。
如果參數為0xfff0000000000000L,結果是負無窮大。
如果參數是在0x7ff0000000000001L通過0x7fffffffffffffffL或範圍0xfff0000000000001L通過0xffffffffffffffffL範圍內的任何值,則結果是NaN。由Java提供任何IEEE754浮點操作可以在相同類型的具有不同位模式的兩個NaN值之間進行區分。楠不同的值是唯一可區分通過使用Double.doubleToRawLongBits方法。
在所有其他情況下,設s,e和m為可以從以下參數計算的三個值:
的int=((bits>>63)==0)? 1:-1;
整數E =(int)的((bits>>52)&0x7ffL);
長M =(E==0)?
(bits&0xfffffffffffffL)<<1:
(bits&0xfffffffffffffL)|0x10000000000000L;
那麼浮點結果等於算術表達式s·m·2e-1075.的值。
注意,此方法可能無法返回一個非數字的雙用完全相同的位模式為long參數。 IEEE 754兩種的NaN,安靜NaN和信號NaN之間的區別。這兩種NaN之間的差異通常是不可見的在Java中。對signaling NaN把他們變成安靜的NaN有不同,但往往大同小異,位模式的算術運算。然而,在某些處理器上只複製信號NaN也執行這種轉換。特別是,複製signaling NaN以將其返回給調用方法可以執行此轉換。所以longBitsToDouble未必能夠返回一個雙帶信號NaN位模式。因此,對於一些長期價值不同,doubleToRawLongBits(longBitsToDouble(開始))可能不等於開始。此外,該特定位模式指信號NaN是依賴於平台;儘管所有NaN位模式,安靜或信號,必須在上述確定的NaN的範圍。
然後就是Float中的intBitsToFloat喲~
螢幕快照 2014-07-05 下午10.29.11
就是你啦
說明:
Returns the float value corresponding to a given bit representation. The argument is considered to be a representation of a floating-point value according to the IEEE 754 floating-point “single format" bit layout.
If the argument is 0x7f800000, the result is positive infinity.
If the argument is 0xff800000, the result is negative infinity.
If the argument is any value in the range 0x7f800001 through 0x7fffffff or in the range 0xff800001through 0xffffffff, the result is a NaN. No IEEE 754 floating-point operation provided by Java can distinguish between two NaN values of the same type with different bit patterns. Distinct values of NaN are only distinguishable by use of the Float.floatToRawIntBits method.
In all other cases, let s, e, and m be three values that can be computed from the argument:
int s = ((bits >> 31) == 0) ? 1 : -1;
 int e = ((bits >> 23) & 0xff);
 int m = (e == 0) ?
                 (bits & 0x7fffff) << 1 :
                 (bits & 0x7fffff) | 0×800000;
Then the floating-point result equals the value of the mathematical expression s·m·2e-150.
Note that this method may not be able to return a float NaN with exactly same bit pattern as the intargument. IEEE 754 distinguishes between two kinds of NaNs, quiet NaNs and signaling NaNs. The differences between the two kinds of NaN are generally not visible in Java. Arithmetic operations on signaling NaNs turn them into quiet NaNs with a different, but often similar, bit pattern. However, on some processors merely copying a signaling NaN also performs that conversion. In particular, copying a signaling NaN to return it to the calling method may perform this conversion. So intBitsToFloat may not be able to return a float with a signaling NaN bit pattern. Consequently, for some int values,floatToRawIntBits(intBitsToFloat(start)) may not equal start. Moreover, which particular bit patterns represent signaling NaNs is platform dependent; although all NaN bit patterns, quiet or signaling, must be in the NaN range identified above.
返回對應於給定的比特表示的float值。該參數被認為是根據IEEE754浮點“單一格式”位佈局的浮點值的表示形式。
如果參數為0x7f800000,結果為正無窮大。
如果參數為0xff800000,結果是負無窮大。
如果參數是範圍0x7f800001到0x7FFFFFFF之間,或在範圍0xff800001到0xFFFFFFFF的任何值,其結果是NaN。由Java提供任何IEEE754浮點操作可以在相同類型的具有不同位模式的兩個NaN值之間進行區分。楠不同的值是唯一可區分通過使用Float.floatToRawIntBits方法。
在所有其他情況下,設s,e和m為可以從以下參數計算的三個值:
的int=((bits>>31)==0)? 1:-1;
整數E =((bits>>23)&0xff)的;
整數M =(E==0)?
(bits&0x7fffff)<<1:
(bits&0x7fffff)|從0×800000;
那麼浮點結果等於算術表達式s·m·2E-150的值。
注意,此方法可能無法返回一個float NaN的具有完全相同位模式為int參數。 IEEE 754兩種的NaN,安靜NaN和信號NaN之間的區別。這兩種NaN之間的差異通常是不可見的在Java中。對signaling NaN把他們變成安靜的NaN有不同,但往往大同小異,位模式的算術運算。然而,在某些處理器上只複製信號NaN也執行這種轉換。特別是,複製signaling NaN以將其返回給調用方法可以執行此轉換。所以intBitsToFloat可能無法返回一個浮點數與信號NaN位模式。因此,對於一些int值,floatToRawIntBits(intBitsToFloat(開始))可能不等於開始。此外,該特定位模式指信號NaN是依賴於平台;儘管所有NaN位模式,安靜或信號,必須在上述確定的NaN的範圍。
好了,兩個方法都看完了,再回來源碼(以double為例)
螢幕快照 2014-07-05 下午10.33.29
還記得longBitsToDouble那短短的源碼吧
螢幕快照 2014-07-05 下午10.17.05
注意:bits是整數
也就是說它會回傳⋯⋯咦?它還使用了其他方法喔!分別是Double中的doubleToRawLongBits和DoubleConsts中的EXP_BIT_MASK,SIGN_CIT_MASK和SIGNIF_BIT_MASK參數
先看doubleToRawLongBits
螢幕快照 2014-07-05 下午10.42.24
說明:
Returns a representation of the specified floating-point value according to the IEEE 754 floating-point “double format" bit layout, preserving Not-a-Number (NaN) values.
Bit 63 (the bit that is selected by the mask 0x8000000000000000L) represents the sign of the floating-point number. Bits 62-52 (the bits that are selected by the mask 0x7ff0000000000000L) represent the exponent. Bits 51-0 (the bits that are selected by the mask 0x000fffffffffffffL) represent the significand (sometimes called the mantissa) of the floating-point number.
If the argument is positive infinity, the result is 0x7ff0000000000000L.
If the argument is negative infinity, the result is 0xfff0000000000000L.
If the argument is NaN, the result is the long integer representing the actual NaN value. Unlike thedoubleToLongBits method, doubleToRawLongBits does not collapse all the bit patterns encoding a NaN to a single “canonical" NaN value.
In all cases, the result is a long integer that, when given to the longBitsToDouble(long) method, will produce a floating-point value the same as the argument to doubleToRawLongBits.
根據IEEE754浮點“雙精度格式”位佈局,並保留非數字(NaN)值,返回指定浮點值的表示。
第63位(0x8000000000000000L選定的位)表示的浮點數的符號。第62-52位(由掩碼0x7ff0000000000000L選定的位)表示指數。第51-0位(由掩碼0x000fffffffffffffL選定的位)表示的浮點數的尾數(有時也稱為尾數)。
如果參數是正無窮大,則結果為0x7ff0000000000000L。
如果參數為負無窮大,則結果為0xfff0000000000000L。
如果參數為NaN,那麼結果是長整數,表示實際NaN值。與doubleToLongBits方法不同,doubleToRawLongBits不垮所有的位模式NaN編碼為一個“規範”NaN值。
在所有情況下,結果是一個長整數,當給予longBitsToDouble(long)方法,會產生一個浮點值相同的參數doubleToRawLongBits。
而這裡(此方法)的value參數就是sign參數
再來就是DoubleConsts中的EXP_BIT_MASK,SIGN_BIT_MASK和SIGNIF_BIT_MASK參數
螢幕快照 2014-07-05 下午10.52.10
現在都清晰了吧
就是說會回傳 一個浮點值相同的參數(sign)&9223372036854775808L 或 一個浮點值相同的參數(magnitude) & 9218868437227405312L 或 4503599627370495L

cos(回傳參數的餘弦值)
螢幕快照 2014-07-05 下午10.58.21
螢幕快照 2014-07-08 下午07.11.17
如果參數為不可表示、未定義或無窮大,那麼結果則為不可表示、未定義的值[這個容易理解吧]
源碼:
螢幕快照 2014-07-08 下午07.19.50
也是一個計算三角函數的方法
Demo:
螢幕快照 2014-07-08 下午07.21.30
容易吧?[笑]
cosh(返回一個雙曲餘弦值)
螢幕快照 2014-07-08 下午07.24.49
螢幕快照 2014-07-08 下午07.25.56
注意這裡:
螢幕快照 2014-07-08 下午07.26.57
雙曲餘弘值中的double x (就是那個參數啦)是定義為螢幕快照 2014-07-08 下午07.29.20其中的e就是這個:
螢幕快照 2014-07-08 下午07.30.20
還記得我們在JDK源碼分析&使用--Math.class篇(1)中看的源碼嗎?
螢幕快照 2014-07-06 下午08.21.25
就是這個e啦~
螢幕快照 2014-07-08 下午07.25.56
如果參數為不可表示、未定義或無窮大,那麼結果則為不可表示、未定義的值
如果參數為0,那麼結果則為1.0
Demo:
螢幕快照 2014-07-08 下午07.36.18
這個也不難理解喲~

decrementExact (返回遞減)
螢幕快照 2014-07-08 下午07.43.37
螢幕快照 2014-07-08 下午07.46.40
返回一個遞減的值,如果結果溢出,就拋出一個異常(拋出ArithmeticException)
螢幕快照 2014-07-08 下午07.53.56
[以int為例]
如果a=Integer的MIN_VALUE值,就拋出一個異常。
Integer.MIN_VALUE:
螢幕快照 2014-07-08 下午07.58.17
Long.MIN_VALUE:
螢幕快照 2014-07-08 下午07.59.37
而最後都是會返回a-1
Demo:
螢幕快照 2014-07-08 下午08.01.26
還不錯的吧
exp(回傳以自然對數底)
螢幕快照 2014-07-08 下午08.11.47
其中參數x則扮演這樣的角色:
螢幕快照 2014-07-08 下午08.14.50
螢幕快照 2014-07-08 下午08.17.06
如果參數為不可表示、未定義,那麼結果則為不可表示、未定義的值
如果正無窮大,那麼結果則為正無窮大
如果參數為負無窮大,那麼結果則為0
注意:計算的結果必須1 ulp範圍內的精確結果

源碼:
螢幕快照 2014-07-08 下午08.22.42
Demo:
螢幕快照 2014-07-08 下午08.23.37

下章見~

No comments:

Post a Comment