導航:首頁 > 源碼編譯 > 浮點數近似方式編譯選項

浮點數近似方式編譯選項

發布時間:2022-04-30 06:59:49

① 浮點小數的表示方法

Java 語言支持兩種基本的浮點類型: float 和 double ,以及與它們對應的包裝類 Float 和 Double 。它們都依據 IEEE 754 標准,該標准為 32 位浮點和 64 位雙精度浮點二進制小數定義了二進制標准。

IEEE 754 用科學記數法以底數為 2 的小數來表示浮點數。IEEE 浮點數用 1 位表示數字的符號,用 8 位來表示指數,用 23 位來表示尾數,即小數部分。作為有符號整數的指數可以有正負之分。小數部分用二進制(底數 2)小數來表示,這意味著最高位對應著值 ?(2 -1),第二位對應著 ?(2 -2),依此類推。對於雙精度浮點數,用 11 位表示指數,52 位表示尾數。IEEE 浮點值的格式如圖 1 所示。

圖 1. IEEE 754 浮點數的格式

因為用科學記數法可以有多種方式來表示給定數字,所以要規范化浮點數,以便用底數為 2 並且小數點左邊為 1 的小數來表示,按照需要調節指數就可以得到所需的數字。所以,例如,數 1.25 可以表示為尾數為 1.01,指數為 0: (-1) 0*1.01 2*2 0

數 10.0 可以表示為尾數為 1.01,指數為 3: (-1) 0*1.01 2*2 3

特殊數字

除了編碼所允許的值的標准范圍(對於 float ,從 1.4e-45 到 3.4028235e+38),還有一些表示無窮大、負無窮大、 -0 和 NaN(它代表「不是一個數字」)的特殊值。這些值的存在是為了在出現錯誤條件(譬如算術溢出,給負數開平方根,除以 0 等)下,可以用浮點值集合中的數字來表示所產生的結果。

這些特殊的數字有一些不尋常的特徵。例如, 0 和 -0 是不同值,但在比較它們是否相等時,被認為是相等的。用一個非零數去除以無窮大的數,結果等於 0 。特殊數字 NaN 是無序的;使用 == 、 < 和 > 運算符將 NaN 與其它浮點值比較時,結果為 false 。如果 f 為 NaN,則即使 (f == f) 也會得到 false 。如果想將浮點值與 NaN 進行比較,則使用 Float.isNaN() 方法。表 1 顯示了無窮大和 NaN 的一些屬性。

表 1. 特殊浮點值的屬性

表達式 結果
Math.sqrt(-1.0) -> NaN
0.0 / 0.0 -> NaN
1.0 / 0.0 -> 無窮大
-1.0 / 0.0 -> 負無窮大
NaN + 1.0 -> NaN
無窮大 + 1.0 -> 無窮大
無窮大 + 無窮大 -> 無窮大
NaN > 1.0 -> false
NaN == 1.0 -> false
NaN < 1.0 -> false
NaN == NaN -> false
0.0 == -0.01 -> true

基本浮點類型和包裝類浮點有不同的比較行為

使事情更糟的是,在基本 float 類型和包裝類 Float 之間,用於比較 NaN 和 -0 的規則是不同的。對於 float 值,比較兩個 NaN 值是否相等將會得到 false ,而使用 Float.equals() 來比較兩個 NaN Float 對象會得到 true 。造成這種現象的原因是,如果不這樣的話,就不可能將 NaN Float 對象用作 HashMap 中的鍵。類似的,雖然 0 和 -0 在表示為浮點值時,被認為是相等的,但使用 Float.compareTo() 來比較作為 Float 對象的 0 和 -0 時,會顯示 -0 小於 0 。

浮點中的危險

由於無窮大、NaN 和 0 的特殊行為,當應用浮點數時,可能看似無害的轉換和優化實際上是不正確的。例如,雖然好象 0.0-f 很明顯等於 -f ,但當 f 為 0 時,這是不正確的。還有其它類似的 gotcha,表 2 顯示了其中一些 gotcha。

表 2. 無效的浮點假定

這個表達式…… 不一定等於…… 當……
0.0 - f -f f 為 0
f < g ! (f >= g) f 或 g 為 NaN
f == f true f 為 NaN
f + g - g f g 為無窮大或 NaN

舍入誤差

浮點運算很少是精確的。雖然一些數字(譬如 0.5 )可以精確地表示為二進制(底數 2)小數(因為 0.5 等於 2 -1),但其它一些數字(譬如 0.1 )就不能精確的表示。因此,浮點運算可能導致舍入誤差,產生的結果接近 ― 但不等於 ― 您可能希望的結果。例如,下面這個簡單的計算將得到 2.600000000000001 ,而不是 2.6 :

double s=0;
for (int i=0; i<26; i++)
s += 0.1;
System.out.println(s);

類似的, .1*26 相乘所產生的結果不等於 .1 自身加 26 次所得到的結果。當將浮點數強制轉換成整數時,產生的舍入誤差甚至更嚴重,因為強制轉換成整數類型會舍棄非整數部分,甚至對於那些「看上去似乎」應該得到整數值的計算,也存在此類問題。例如,下面這些語句:

double d = 29.0 * 0.01;
System.out.println(d);
System.out.println((int) (d * 100));

將得到以下輸出:

0.29
28

這可能不是您起初所期望的。

浮點數比較指南

由於存在 NaN 的不尋常比較行為和在幾乎所有浮點計算中都不可避免地會出現舍入誤差,解釋浮點值的比較運算符的結果比較麻煩。

最好完全避免使用浮點數比較。當然,這並不總是可能的,但您應該意識到要限制浮點數比較。如果必須比較浮點數來看它們是否相等,則應該將它們差的絕對值同一些預先選定的小正數進行比較,這樣您所做的就是測試它們是否「足夠接近」。(如果不知道基本的計算范圍,可以使用測試「abs(a/b - 1) < epsilon」,這種方法比簡單地比較兩者之差要更准確)。甚至測試看一個值是比零大還是比零小也存在危險 ―「以為」會生成比零略大值的計算事實上可能由於積累的舍入誤差會生成略微比零小的數字。

NaN 的無序性質使得在比較浮點數時更容易發生錯誤。當比較浮點數時,圍繞無窮大和 NaN 問題,一種避免 gotcha 的經驗法則是顯式地測試值的有效性,而不是試圖排除無效值。在清單 1 中,有兩個可能的用於特性的 setter 的實現,該特性只能接受非負數值。第一個實現會接受 NaN,第二個不會。第二種形式比較好,因為它顯式地檢測了您認為有效的值的范圍。

清單 1. 需要非負浮點值的較好辦法和較差辦法
// Trying to test by exclusion -- this doesn't catch NaN or infinity
public void setFoo(float foo) {
if (foo < 0)
throw new IllegalArgumentException(Float.toString(f));
this.foo = foo;
}
// Testing by inclusion -- this does catch NaN
public void setFoo(float foo) {
if (foo >= 0 && foo < Float.INFINITY)
this.foo = foo;
else
throw new IllegalArgumentException(Float.toString(f));
}

不要用浮點值表示精確值

一些非整數值(如幾美元和幾美分這樣的小數)需要很精確。浮點數不是精確值,所以使用它們會導致舍入誤差。因此,使用浮點數來試圖表示象貨幣量這樣的精確數量不是一個好的想法。使用浮點數來進行美元和美分計算會得到災難性的後果。浮點數最好用來表示象測量值這類數值,這類值從一開始就不怎麼精確。

用於較小數的 BigDecimal

從 JDK 1.3 起,Java 開發人員就有了另一種數值表示法來表示非整數: BigDecimal 。 BigDecimal 是標準的類,在編譯器中不需要特殊支持,它可以表示任意精度的小數,並對它們進行計算。在內部,可以用任意精度任何范圍的值和一個換算因子來表示 BigDecimal ,換算因子表示左移小數點多少位,從而得到所期望范圍內的值。因此,用 BigDecimal 表示的數的形式為 unscaledValue*10 -scale 。

用於加、減、乘和除的方法給 BigDecimal 值提供了算術運算。由於 BigDecimal 對象是不可變的,這些方法中的每一個都會產生新的 BigDecimal 對象。因此,因為創建對象的開銷, BigDecimal 不適合於大量的數學計算,但設計它的目的是用來精確地表示小數。如果您正在尋找一種能精確表示如貨幣量這樣的數值,則 BigDecimal 可以很好地勝任該任務。

所有的 equals 方法都不能真正測試相等

如浮點類型一樣, BigDecimal 也有一些令人奇怪的行為。尤其在使用 equals() 方法來檢測數值之間是否相等時要小心。 equals() 方法認為,兩個表示同一個數但換算值不同(例如, 100.00 和 100.000 )的 BigDecimal 值是不相等的。然而, compareTo() 方法會認為這兩個數是相等的,所以在從數值上比較兩個 BigDecimal 值時,應該使用 compareTo() 而不是 equals() 。

另外還有一些情形,任意精度的小數運算仍不能表示精確結果。例如, 1 除以 9 會產生無限循環的小數 .111111... 。出於這個原因,在進行除法運算時, BigDecimal 可以讓您顯式地控制舍入。 movePointLeft() 方法支持 10 的冪次方的精確除法。

使用 BigDecimal 作為互換類型

SQL-92 包括 DECIMAL 數據類型,它是用於表示定點小數的精確數字類型,它可以對小數進行基本的算術運算。一些 SQL 語言喜歡稱此類型為 NUMERIC 類型,其它一些 SQL 語言則引入了 MONEY 數據類型,MONEY 數據類型被定義為小數點右側帶有兩位的小數。

如果希望將數字存儲到資料庫中的 DECIMAL 欄位,或從 DECIMAL 欄位檢索值,則如何確保精確地轉換該數字?您可能不希望使用由 JDBC PreparedStatement 和 ResultSet 類所提供的 setFloat() 和 getFloat() 方法,因為浮點數與小數之間的轉換可能會喪失精確性。相反,請使用 PreparedStatement 和 ResultSet 的 setBigDecimal() 及 getBigDecimal() 方法。

對於 BigDecimal ,有幾個可用的構造函數。其中一個構造函數以雙精度浮點數作為輸入,另一個以整數和換算因子作為輸入,還有一個以小數的 String 表示作為輸入。要小心使用 BigDecimal(double) 構造函數,因為如果不了解它,會在計算過程中產生舍入誤差。請使用基於整數或 String 的構造函數。

構造 BigDecimal 數

對於 BigDecimal ,有幾個可用的構造函數。其中一個構造函數以雙精度浮點數作為輸入,另一個以整數和換算因子作為輸入,還有一個以小數的 String 表示作為輸入。要小心使用 BigDecimal(double) 構造函數,因為如果不了解它,會在計算過程中產生舍入誤差。請使用基於整數或 String 的構造函數。

如果使用 BigDecimal(double) 構造函數不恰當,在傳遞給 JDBC setBigDecimal() 方法時,會造成似乎很奇怪的 JDBC 驅動程序中的異常。例如,考慮以下 JDBC 代碼,該代碼希望將數字 0.01 存儲到小數欄位:

PreparedStatement ps =
connection.prepareStatement("INSERT INTO Foo SET name=?, value=?");
ps.setString(1, "penny");
ps.setBigDecimal(2, new BigDecimal(0.01));
ps.executeUpdate();

在執行這段似乎無害的代碼時會拋出一些令人迷惑不解的異常(這取決於具體的 JDBC 驅動程序),因為 0.01 的雙精度近似值會導致大的換算值,這可能會使 JDBC 驅動程序或資料庫感到迷惑。JDBC 驅動程序會產生異常,但可能不會說明代碼實際上錯在哪裡,除非意識到二進制浮點數的局限性。相反,使用 BigDecimal("0.01") 或 BigDecimal(1, 2) 構造 BigDecimal 來避免這類問題,因為這兩種方法都可以精確地表示小數。

② C語言float類型

C語言float類型是單精度浮點類型。

對於每一個浮點數,二進制編碼的表示:(-1)^s * M * e。
s:是指的符號位,有兩種取值,為0時,表示正浮點數。為1時表示負的浮點數。
M:是有效位數。
e:是指數。實際上這是一個偏置指數。

一般來說,float單精度浮點類型佔32個二進制位,其中s符號位佔1位,M有效數位佔23位,e指數位佔8位。

③ C語言中的浮點數的問題

在32位編譯器中,按照IEEE754標准,單精度浮點數float固定佔4個位元組,其中符號位1位,階碼8位(表示範圍-126~127),尾數23位(表示範圍1.0000...000~1.111111...111)共32位。按照此標准,能表示的最大數字是2^127*2=3.4x10^38,即3.4E38。
你可以理解為計算機中的科學計數法,只不過是2的冪而不是10的冪,即±M*2^E。其中M為尾數,E為階碼

④ C語言學習,浮點型數據的問題

我們說的浮點數包括單精度浮點數和雙精度浮點數。
這里,我先拿單精度浮點數來解釋你的問題。

單精度數,是指計算機表達實數近似值的一種方式。VB中,Single(單精度浮點型)變數存儲為 IEEE 32 位(4 個位元組)浮點數值的形式,它的范圍在負數的時候是從 -3.402823E38 到 -1.401298E-45,而在正數的時候是從 1.401298E-45 到 3.402823E38 。
單精度存儲格式
符號位S(sign) - 1bit
0代表正號,1代表負號。

指數位E(exponent) - 8bit
E的取值范圍為0-255(無符號整數),實際數值e=E-127。
有時E也稱為「移碼」,或不恰當的稱為「階碼」(階碼實際應為e) 就是你所說的p。

尾數位M(mantissa) - 23bit
M也叫有效數字位(sinificand)、系數位(coefficient), 甚至被稱作「小數」。
在一般情況下,m=(1.M)2,使得實際起作用范圍為1≤尾數<2。
為了對溢出進行處理,以及擴展對接近0的極小數值的處理能力。

單精度浮點數實例:
對於內部存儲數據(00111111 01100110 01100110 01100110)2:
符號位
(最左側)S=0。這表示是個正數

指數
(左側第2-9位)E=(01111110)2=(126)10,所以s=S-127=-1。

尾數
(最後的23位)M=(1100110 01100110 01100110)2,m=(1.M)2=(1.7999999523162841796875)10
該二進制小數轉為10進制的計算方式為1 + (1/2+1/4) + (1/32+1/64) + (1/512+1/1024)……

實際值
N=1.7999999523162841796875*2-1=0.89999997615814208984375
(其實,這個數據是0.9的單精度浮點數的實際內部存儲,可以看到有一定的誤差)

單精度浮點數的表示範圍及說明
表示範圍
最大表示範圍:單精度浮點數可以表示的范圍為±3.40282 * 1038(1.1111...12*2127)
接近於0的最小值:單精度浮點數可以表示1.175 * 10-38(1.00...02*2-126)的數據而不損失精度。
當數值比以上值小的時候,將會由於尾數的有效位數減少而逐步喪失精度(IEEE 754的規定),或者有的系統則直接採用0值來簡化處理過程。

精度
單精度浮點數的實際有效精度為24位二進制,這相當於 24*log102≈7.2 位10進制的精度,所以平時我們說「單精度浮點數具有7位精度」。(精度的理解:當從1.000...02變化為1.000...12時,變動范圍為2-23,考慮到因為四捨五入而得到的1倍精度提高,所以單精度浮點數可以反映2-24的數值變化,即24位二進制精度)

誤差
浮點數以有限的32bit長度來反映無限的實數集合,因此大多數情況下都是一個近似值。同時,對於浮點數的運算還同時伴有誤差擴散現象。
特定精度下看似相等的兩個浮點數可能並不相等,因為它們的最小有效位數不同。
由於浮點數可能無法精確近似於十進制數,如果使用十進制數,則使用浮點數的數學或比較運算可能不會產生相同的結果。
如果涉及浮點數,值可能不往返。值的往返是指,某個運算將原始浮點數轉換為另一種格式,而反向運算又將轉換後的格式轉換回浮點數,且最終浮點數與原始浮點數相等。由於一個或多個最低有效位可能在轉換中丟失或更改,往返可能會失敗。

關於雙精度型:
目前大多數高級語言(包括C)都按照IEEE-754標准來規定浮點數的存儲格式,IEEE754規定,單精度浮點數用4位元組存儲,雙精度浮點數用8位元組存儲,分為三個部分:符號位、階和尾數。階即指數,尾數即有效小數位數。單精度格式階佔8位,尾數佔24位,符號位1位,雙精度則為11為階,53位尾數和1位符號位。

⑤ 浮點數問題

樓主的問題應該是浮點數在內存中的存儲,浮點數有float和double兩種。你耐心看看下面的解釋就懂了。
任何數據在內存中都是以二進制的形式存儲的,例如一個short型數據1156,其二進製表示形式為00000100 10000100。則在Intel CPU架構的系統中,存放方式為 10000100(低地址單元) 00000100(高地址單元),因為Intel CPU的架構是小端模式。但是對於浮點數在內存是如何存儲的?目前所有的C/C++編譯器都是採用IEEE所制定的標准浮點格式,即二進制科學表示法。
在二進制科學表示法中,S=M*2^N 主要由三部分構成:符號位+階碼(N)+尾數(M)。對於float型數據,其二進制有32位,其中符號位1位,階碼8位,尾數23位;對於double型數據,其二進制為64位,符號位1位,階碼11位,尾數52位。
31 30-23 22-0
float 符號位 階碼 尾數
63 62-52 51-0
double 符號位 階碼 尾數
符號位:0表示正,1表示負
階碼:這里階碼採用移碼表示,對於float型數據其規定偏置量為127,階碼有正有負,對於8位二進制,則其表示範圍為-128-127,double型規定為1023,其表示範圍為-1024-1023。比如對於float型數據,若階碼的真實值為2,則加上127後為129,其階碼表示形式為10000010
尾數:有效數字位,即部分二進制位(小數點後面的二進制位),因為規定M的整數部分恆為1,所以這個1就不進行存儲了。
下面舉例說明:
float型數據125.5轉換為標准浮點格式
125二進製表示形式為1111101,小數部分表示為二進制為 1,則125.5二進製表示為1111101.1,由於規定尾數的整數部分恆為1,則表示為1.1111011*2^6,階碼為6,加上127為133,則表示為10000101,而對於尾數將整數部分1去掉,為1111011,在其後面補0使其位數達到23位,則為11110110000000000000000
則其二進製表示形式為
0 10000101 11110110000000000000000,則在內存中存放方式為:
00000000 低地址
00000000
11111011
01000010 高地址
而反過來若要根據二進制形式求算浮點數如0 10000101 11110110000000000000000
由於符號為為0,則為正數。階碼為133-127=6,尾數為11110110000000000000000,則其真實尾數為1.1111011。所以其大小為
1.1111011*2^6,將小數點右移6位,得到1111101.1,而1111101的十進制為125,0.1的十進制為1*2^(-1)=0.5,所以其大小為125.5。
同理若將float型數據0.5轉換為二進制形式
0.5的二進制形式為0.1,由於規定正數部分必須為1,將小數點右移1位,則為1.0*2^(-1),其階碼為-1+127=126,表示為01111110,而尾數1.0去掉整數部分為0,補齊0到23位00000000000000000000000,則其二進製表示形式為
0 01111110 00000000000000000000000
由上分析可知float型數據最大表示範圍為1.11111111111111111111111*2^127=3.4*10^38
對於double型數據情況類似,只不過其階碼為11位,偏置量為1023,尾數為52位

⑥ 浮點數在計算機中是如何表示的

實型變數分為兩類:

單精度型和雙精度型,其類型說明符為float 單精度說明符,double 雙精度說明符。在Turbo C中單精度型佔4個位元組(32位)內存空間,其數值范圍為3.4E-38~3.4E+38,只能提供七位有效數字。

雙精度型佔8 個位元組(64位)內存空間,其數值范圍為1.7E-308~1.7E+308,可提供16位有效數字。

⑦ 關於c語言中如何定義浮點數

需要准備的材料分別有:電腦、C語言編譯器。

1、首先,打開C語言編譯器,新建一個初始.cpp文件,例如:test.cpp。

⑧ 計算機組成原理——浮點數表示方法

就是在二進制中,一個數的小數點可以可以通過乘以2的冪次來改變位置,這是其原理 。

浮點數的組成:階符+ 階碼 +數符+ 尾數

計算機中表示浮點數的字長通常為32位,其中7位作階碼,1位為階符,23位尾數,1位作數符

例如用2個位元組表示一個浮點數(32寫起來麻煩,所以用2個位元組就是16位來舉例,呵呵希望諒解) (72.45x10^5)D先換成普通二進制數(11011101000110011001000)B

然後開始像十進制數的科學計數法那樣寫成約等於(0.1101110)Bx(2^23)D

之後再將後半部分的(2^23)D轉換成(2^10111)B

於是整個數就變成了(0.1101110x2^10111)B

在計算機中表示成0001011101101110 其中第一個0是階符表示指數是正的第九個0表示尾數是正的他們中間的就是階碼,後面的就是尾數。

⑨ 浮點數比較可以使用float compare方法嗎

計算機內的浮點數是有一定的字長和精度的。
如果是2個float型的浮點數,你用 float compare方法當然可以。
如果有1個或2個是double型的浮點數,用 float compare方法 很可能因精度引起的誤差而出錯。
通常,最好根據具體情況,自己寫 比較式 較好。 你可以假定 兩數相減的絕對值 小於 某個誤差值 就是相等,若是不相等時,再用 > 或 < 判斷大小。

⑩ C語言中的浮點值是什麼意思

就是常說的小數,浮點是意思就是數字中有個漂浮的點,這個點就是常說的小數點。

1、C語言中均支持兩種浮點數,float和double。
其中double的精度,和表示範圍比float要大。
另外,部分編譯器支持更大精度的long double,但不是所有的編譯器都支持。
以上為三種浮點數的類型。在定義的時候,需要以
TYPE var=init_value;
的方式定義,功能為定義一個名字為var,類型為TYPE的變數,並賦值初始值為init_value。
其中=init_value部分可以省略。
2、比如定義一個float類型的浮點變數為
float f;
定義一個類型為double的浮點型變數,並初始化值為1.234,寫作
double d = 1.234;

閱讀全文

與浮點數近似方式編譯選項相關的資料

熱點內容
單片機微小電阻測量 瀏覽:134
表格25兆怎麼壓縮 瀏覽:65
java開發公司的 瀏覽:127
東風天錦壓縮車工作指示燈不亮 瀏覽:981
劍俠情緣1源碼 瀏覽:528
cad2011怎麼轉換成pdf格式 瀏覽:962
傳祺gs5安卓車機如何還原車機 瀏覽:898
單片機和編程器互相傳輸數據 瀏覽:88
app訂單怎麼取消 瀏覽:465
程序員用雙顯示器有什麼作用 瀏覽:609
網約車演算法殺熟 瀏覽:4
卡薩帝用的什麼壓縮機 瀏覽:153
350乘20演算法 瀏覽:90
自助編程軟體app 瀏覽:438
伺服器如何看日活數 瀏覽:686
數控車床原理圖及編程 瀏覽:289
java文件流下載 瀏覽:340
編程工作工資多少 瀏覽:441
專業安全文件夾 瀏覽:781
表格里的根號演算法怎麼打 瀏覽:197