關於浮點數

2021-06-25 23:34:20 字數 2684 閱讀 2955



oi/acm中經常要用到小數來解決問題(概率、計算幾何等),但是小數在計算機中的儲存方式是浮點數而不是我們在作數**算中的數,有精度的限制。

以下以gun c++為準,其他語言(或編譯器)也差不了多少。本文競賽向。

一、基礎篇

1、一般浮點數使用double,範圍為大概為-10^308 ~ 10^308,有效精度為15~16位10進製數。

2、一般沒事(比如記憶體問題)不用float,而使用double,乙個double佔8個位元組。

3、資訊學競賽一般使用scanf和printf輸入輸出,而浮點數的輸入是scanf("%lf", &x),浮點數的輸出是printf("%f", x),注意兩個是不一樣的。使用printf("%lf", x)來輸出浮點數有可能會出錯,因為標準中規定double輸出是使用"%f"的,並非所有編譯器都實現了"%lf"的輸出(比如poj的g++就沒有)。

4、在實在沒有辦法的情況下可以使用long double,但標準只規定了其精度一定不小於double,有可能等於double請注意。

5、double的精度有限,並不是精確的儲存數字,而且它是二進位制儲存,如下圖,0.1 * 10不等於1,因為0.1在計算機中不是我們認為的1/10,下圖有0.1在double下的值,可以看出並不完全等於0.1。

6、為了解決上面不能直接比較的問題,我們可以設定乙個精度eps,來輔助我們檢驗兩個數是否非常接近。eps的設定要看題目具體情況,一般情況下可以設成1e-8。

定義函式:?

12

3

4

inlineintsgn(doublex)

用上述函式來判斷乙個數是否大於小於或等於0。

x = 0 寫成 sgn(x) == 0

x < 0 寫成 sgn(x) < 0

x > 0 寫成 sgn(x) > 0

x > y 寫成 sgn(x - y) > 0

x == y 寫成 sgn(x - y) == 0

x >= y 寫成 sgn(x - y) >= 0

以此類推。

7、上述函式的一種常數優化的寫法:?

12

3

inlineintsgn(doublex)

二、高階篇(陷阱篇)

1、在競賽中,可能存在給乙個double多次計算後,非常接近0的情況,但是,它可能是-0.000000000000000001(一下子舉不出實際的例子……),這時輸出會變成-0.00,在一部分精確比較的題目上可能會出錯,解決方案為輸出的時候加上乙個eps(當然不能排除出題人自己煞筆的情況……),即printf("%f", ans + eps)。

2、如果乙個double,要把乙個陣列裡的浮點數累加起來(即 double sum = accumlate(arr.begin(), arr.end(), 0)),如果陣列裡的數相差可能會比較大,應該從小到大累加。否則可能會發生加了乙個很大的浮點數之後,再加乙個很小的浮點數,因為精度的原因,跟沒加一樣(比如乙個極端的例子,1e100 + 1e-100還是等於1e100)。因為比較小的數多了,還是會影響到答案的,並不是可以簡簡單單被忽略的。

3、在計算乙個數減去一組數的時候(即double sum = x - accumlate(arr.begin(), arr.end(), 0)),應該先把陣列裡的數全加起來,再用那個數來減。否則跟上面一樣,可能會出現減去了乙個很小的數,跟沒減一樣。

4、二分的時候,eps設定不當,可能會出現奇怪的問題(特別是有多次二分而對著兩次二分要求的精度不一樣的時候),這時可以採取另一種寫法:?

12

3

4

5

6

7

8

doublebinary_search(doublel,doubler)

returnl;

}

迴圈次數可按需設定,一般100都夠,對時間要求高可以設小一點。

5、在連乘的時候,浮點數可能會丟比較多的精度,此時可以利用公式x1 * x2 * …… * xn = exp(ln(x1 * x2 * …… * xn)) = exp(ln(x1) + ln(x2) + ……ln(xn)),取他們的對數相加,再求次冪。

比如在計算階乘的時候,可以:?

12

3

4

5

6

doublefactorial(intn)

當然有必要的時候(其實是大多時候)我們可以先不exp()先返回,作完後續運算再exp()

關於浮點數的比較

include int main return 0 這段 編譯會有警告 warning c4305 initializing truncation from const double to float 也就是說,初始化變數的時候,將double型截斷為float型,有精度損失.同理,則if語句裡面的...

浮點數 儲存

關鍵字 體系結構 ieee754 浮點數 儲存 main 如果不執行上面的 讓我們來直接判斷,輸出的結果會是什麼?而在你執行程式之後,結果卻很讓人詫異 123.456001。為什麼會是123.456001?有六位小數可以理解,最後那個1是為何?有很多人解釋說最後那個1是亂碼,隨機的。嘿嘿 其實無論你...

浮點數操作

float fx 49.03f int nx fx 100 printf d nx 執行上述 結果 4902。用vc6.0,2005,gcc編譯執行結果都是一樣。為什麼會這樣呢,是因為浮點數運算具有不精確性。其實編譯上面的 編譯器會有警告的。warning c4244 initializing co...