2008年5月6日 星期二

獲得究極的精準度

在C語言中浮點數的精準度是大家頭痛的問題

基本上如果是我我會盡量少用浮點數這個宣告




先目測看下面程式片段的執行結果吧!


x=(float)3/7;
y=(float)1/7;

printf("%f\n",(float)x/y);

if(x/y==3.000000)
printf("(3/7)/(1/7)==3.000000\n");
else
printf("(3/7)/(1/7)!=3.000000\n");


非常可惜你應該猜錯了
正確答案如下


3.000000
(3/7)/(1/7)!=3.000000


搞什麼鬼阿?!
為什麼出現這麼矛盾的結果呢?

其實在電腦中所有的資訊都是由二進位所紀錄成的
所以有的數並不能準確的被儲存

像(0.3)10=(0.010011001100...)2
是一個循環小數
所以電腦會儲存前面部分的位數
像0.0100110011=2.99805大約等於3這樣
所以上面的分數除法把這個誤差給挖大了,雖然輸出看起來還是3,實際上已經差很遠了...

那要怎麼突破呢?
其實可以把它儲存成分數
X_S是X的分子
X_M是X的分母
Y_S是Y的分子
Y_M是Y的分母

再運用分子分母通分後相除,自然就能算出十分精準的數了。


x_s=3;
x_m=7;

y_s=1;
y_m=7;

printf("%f\n",(float) ( (x_s*y_m) / (x_m*y_s) ) );

if((float) ( (x_s*y_m) / (x_m*y_s) ) ==3.000000)
printf("(3/7)/(1/7)==3.000000\n");
else
printf("(3/7)/(1/7)!=3.000000\n");



3.000000
(3/7)/(1/7)==3.000000


其實用結構可以寫的更乾脆
用這個方法可以幾近表示成幾近所有的有理數

夠酷吧!!

沒有留言:

張貼留言

Related Posts Plugin for WordPress, Blogger...