C 語言 IEEE754 浮點數操作 - 序
一開始,筆者只針對 IEEE754 發過一篇文 - [浮點數] IEEE754, C/C++ 浮點數誤差 ,但基於以下二個原因,我決定實做,並說明與紀錄此系列文章。
1. 欲擬 Online IEEE754 Converter ,做離線版本之 Converter 查詢。
2. 一些常被錯誤使用之浮點數技巧 (如判斷浮點數是否為整數、取浮點數上下限整數)
這系列文章主要在探討 IEEE754 浮點數表示法之特性,文章裡之內容有些冷門,目前顯少見人於網路上做廣泛之探討,一方面這部份要徹底了解,直接去 K Spec 即可;一方面也許認為對於程式、升學考之投資報酬率不高。
筆者較擅 C/C++ 程式語言,此系列文章將實際以高階程式語言實作之,實作之內容大致如下
1. 查看 2 進位 / 16 進位值。
2. 取得/設定 IEEE754 各欄欄位之 16 進位值。
3. 取得/設定 IEEE754 正規化數值。
4. 取得/設定 IEEE754 特殊值。
實作過程用了大量之 pointer 概念與技巧,若本身對於指標沒一定程度了解,或一知半解,不適合鑽研程式碼;若對指標自信有一定程度了解,只在缺乏練習,本文所探討之議題可做為練習題目之參考。撰碼過程中,盡可能以「程式碼清晰度」為第一優先,而不以「執行速度」為第一優先,即使有許多程式碼部份是可再化簡,筆者此處便予以保留。
另程式碼中,必有部份效率極差,且有明顯之改善方案,如對一個浮點數取絕對值,此系列文提供將 sign bit 清 0 之作用函式,但並非鼓勵讀者這麼做,效率差,卻仍提它,原因是為保持此系列文之完整性,而並非鼓勵各位讀者以較麻煩之指標方式,取代現有較簡便,可解決問題之方式。
在閱完此系列文之後,希望能修正部份讀者一些謬誤
1. 浮點數有精度問題,且有效位數不是以十進位模式思考
以畢氏定理為觀看,給定 x,y,其斜邊 z = sqrt(x*x + y*y),
再令 x2 = x / 10.0 , y2 = y/10.0 , z2 = z/10.0,
則 x2*x2 + y2*y2 = z2 * z2 未必成立,
且不成立的機會比成立的機會還要大不少,
依此原則,看個 demo code
#include <stdio.h>
#include <math.h>
int main()
{
double
x=3.1, y=4.5,
z=sqrt(x*x+y*y);
double
x2=x/10.0
, y2=y/10.0,
z2=z/10.0;
if(x2*x2 + y2*y2 == z2*z2) printf("success\n");
else printf("fail\n");
return
0;
}
結果輸出是 fail。
2. 沒有任何一個方法,可以簡便判斷一個浮點數是否為整數。
double x = 10.0;
x == (int)x;
這方法不正確。
3. 也沒有任何一個方法,可以簡便對一浮點數取下限整數。
double x=12.2;
int y = (int)x;
這方法也不正確。
同時,若讀者讀完此系列文章前六篇 (目錄裡至 [浮點數] C/C++ 浮點數特殊值 ),
事實上也可自己以 C language 寫一份 IEEE754 查詢程式,
也不用每次上 Online Converter 再去查,客制化也可自己搞。
最後,祝學習順利