Board logo

主題: [C&C++] [問題]關於c的浮點數 [打印本頁]

發表人: XYZ007    時間: 2011-2-16 07:08 PM     主題: [問題]關於c的浮點數

我看的書(C Primer Plus 5/e)中提到:
    在標準的c語言中,float至少可表示六個有效數字(significant figure),且數字範圍至少為10^(-37) 到10^37 。第一個規定六個有效數字的意思是--例如,以float型態表示33.333333這個數字時,至少前六位數字是正確的;而第二個規定有效範圍的意思則是方便用來表示太陽的質量(2.0e30公斤)、質子的電荷(1.6e-19庫侖)或是國債…等等這類的數值。
(中間略過)
    此外,c還提供了double浮點數型態。double的數字範圍跟float一樣,不過其有效數字至少可達10個數字,…(以下略過)
    c允許第三種浮點數型態:long double,其目的是為了增加精確度,不過c只保證long double至少和double一樣的精準。

另外一本(visual c++6教學範本)則說float為7位有效位數,double為15位。

兩本寫的不太一樣,該聽哪一本的?
想問的是,這個有效數字是怎麼看,像33.333333是前六個也就是33.3333至少是正確的嗎?
有效數字和數字範圍差別在哪?數字範圍是指可以顯示出來的是10^(-37) 到10^37,在這之間的值有可能是不正確的?
還請大大指教一下,謝謝
發表人: cld    時間: 2011-2-16 08:09 PM

從基本的C來說 (非c++)

float 有 6個有效位數(小數點以後),範圍為 10^(-38) ~ 10^(38)
----------------------------------------------
  (+-1.175494E-38 ~ +-3.402823E+38)
有效位數為小數點後之數字 ,而數質範圍如 () 內之範圍
----------------------------------------------


double 有 15個有效位數(小數點以後),範圍為 10^(-308) ~ 10^(308)

基本上通則是如此

但電腦儲存資料是以二進制處理
故實際數值範圍並非整數
而不同之電腦系統因硬體不同
軟體也可能會為之修正
實際結果
以所使用之 C編譯器而定
發表人: XYZ007    時間: 2011-2-16 09:47 PM

那假如double有15個有效位數,308-15=293
那意思是有293個不精確的小數?
發表人: cld    時間: 2011-2-16 10:01 PM

308 指的是 10^308 次方
因為實際放有效值的只有 8 byte
故實際有效的數值是 (2^64)/2
有效位數大約是15位(超過的部分會被忽略,處理模式由C編譯器決定)
多餘的部分是由 次方部分所涵蓋
而非 308-15 的狀態

[cld 在  2011-2-16 10:09 PM 作了最後編輯]
發表人: ericshliao    時間: 2011-3-19 05:56 PM

照我看起來,兩個寫的沒衝突。
VC++只適用在MS的平台上,而C Primer Plus則是泛指各個implementation,所以後者寫的比較概括,而前者可以寫的很確定。如果樓主是用MS的OS,那當然聽MS的,如果不是,那就看各個平台了。
不過,我得承認,我寫的程式從來沒去仔細留意數值的精準度到幾個位數。
發表人: julius    時間: 2011-3-21 10:34 PM

有點離題,
不過, 還是推薦一份 1991 年 David Goldberg 發表關於 "浮點運算" 小有名氣的文章,

文章名稱 : "What Every Computer Scientist Should Know About Floating-Point Arithmetic"
http://download.oracle.com/docs/ ... 3/ncg_goldberg.html

關於浮點運算的網站,
http://floating-point-gui.de/
發表人: ChocoMocha    時間: 2011-3-22 05:35 PM

float = (+/-) 1. m X 2^ (e)
1 bit ......... Sign
8 bits......... 次方
23 bits....... 小數

2^(23) = 8388608 => 七個位數...

所以...假設你有兩個float A and B...
A = 0.1111111
B = 0.00000000000000001
A + B = 0.11111110000000001
但是float只有大概七個位數的準確度...所以 A+B 會只剩 0.1111111
也就是說...如果要對兩個相差超過七位數以上的數作加減乘除...就很有可能會掉一些精準值...
大部分的軟體計算都不需要這麼精確...除非你在算的是錢!!!

p.s. A 跟 B 都是十進制
發表人: zxvf    時間: 2011-4-14 07:19 PM

關於精準度, 可由「定點數」應用在小數表示法比較有感覺

舉 int16 的例子來說,
一般認定的範圍是  -32178 (0x8000) ~ 32767 (0x7FFF)
但在意義上, 可以解釋成 -1 ~ +1 , 只要把小數點放在第 15 個 bits, 邏輯上就是 right shift 15 bits
而通常這個變數可能會寫成 Q15 (表示小數點的位置)

依照不同的應用, 你可以調整小數點的位置, 而得到不同數值範圍
但實務上, 小數點的位置在設計程式的時候就決定了, 就不會換了
要換小數點的位置, 當然也可以, 不過就要一些技巧...

而浮點數會記錄小數點的位置, 可以動態調整, 所以表示範圍是動態的
專用名詞是 dynamic range
由於浮點數要盡可能表示有效位數, 所以正規化之後, 第一個 bit 必須為 1
也因為第一個 bit 為 1, 就可以省去

回到精準度的部分, 不管浮點數 or 定點數
若有一個值是
0.11001b (二進位)
則其 10 進位的值是
0 +
1 x 1/2 +
1 x 1/4 +
0 x 1/8 +
0 x 1/16 +
1 x 1/32
= 0.78125

所以, 要以 10 進位來說精準度有幾個位數, 個人覺得很難理解
以 2 進位來說, 就很容易... 就看有幾個 bits 了




歡迎光臨 TWed2k (http://twed2k.org/) Powered by Discuz! 4.1.0