一、了解定點數和浮點數
計算機中的實數處理一般有兩種方法:定點數和浮點數。定點數指的是小數點位置固定的數值,典型的例子是貨幣的計算,小數點後兩位即為分。
浮點數指的是小數點位置可以向左或向右浮動的數值,這裡的「浮動」指的是小數點對數值精度的影響。
比如,$1.23 \times 10^4$和$12.3 \times 10^3$都可以用科學計數法表示為1.23e+04,但是前者的小數點的位置在大數的後面,而後者小數點的位置在大數的前面。所以,浮點數的表示範圍相對較大,但是精度相對較低。
二、定點數的詳解
在計算中,我們通常需要進行浮點數(實數)和定點數(整數)之間的轉換。有時候,我們需要把實數乘以一個精度因子,再將其轉換成整數,這就是定點數的表示方法。
#include <stdio.h> #define Q 8 // 小數部分的位數 #define QQ (1<<Q) // 2^Q #define QQ2 (1< %d\n", a, a_fix); printf("b: %.2lf -> %d\n", b, b_fix); printf("a+b: %.4lf\n", fix(a_fix + b_fix)); return 0; }
上述代碼實現了將小數部分為8位的實數轉化為整數操作,例如將2.25轉換為$2.25 \times 2^8=576$。
三、浮點數的詳解
在計算機內部,單精度浮點數32位,雙精度浮點數64位。由於存儲空間的限制,無法完全精確地表示實數。所以,計算機內部的浮點數通常採用科學計數法表示,在IEEE754標準中,單精度浮點數最高位表示符號,接著是指數部分,然後是尾數部分。
#include <stdio.h> int main() { float a = 1.2345; double b = 12.345; printf("a: %.10f\n", a); printf("b: %.15lf\n", b); return 0; }
輸出結果為:
a: 1.2344999313 b: 12.345000000000000
從輸出結果可以看出,浮點數的精度不如定點數高。
四、小數點的移位問題
在浮點數的運算中,容易出現小數點的移位問題。比如,我們需要將一個浮點數加上一個整數,但是因為小數點位置的不同,可能會出現問題。
#include <stdio.h> int main() { double a = 1.0, b = 100000000000.0; int c = 1; printf("a+b: %.1lf\n", a+b); // 輸出:100000000001.0 printf("(a+c)+b: %.1lf\n", (a+c)+b); // 輸出:100000000002.0 printf("a+(c+b): %.1lf\n", a+(c+b)); // 輸出:100000000001.0 return 0; }
從輸出結果可以看出,在浮點數的運算中,加法並不滿足結合律。
五、避免浮點數誤差
為了避免浮點數運算中出現誤差,我們可以採用避免小數點移位的方法,即將小數轉換為整數進行運算。
#include <stdio.h> int main() { double a = 1.0, b = 100000000000.0; int a_fix = a * 1000; int b_fix = b; printf("a_fix+b_fix: %.1lf\n", (double)(a_fix+b_fix)/1000); // 輸出:100000000001.0 return 0; }
上述代碼中,我們將浮點數乘以一個精度因子1000,再將其轉換為整數進行計算。最後再將計算結果轉換為浮點數。
六、整數溢出問題
在使用定點數時,有可能會出現整數溢出的問題。當定點數的位數不夠用時,需要向左移動小數點,此時整數位數就會增加,如果整數位數過大,就會超出計算機所能表示的範圍。
#include <stdio.h> #define Q 3 // 小數部分的位數 #define QQ (1<<Q) // 2^Q #define fract(x) ((int)((x)*QQ+0.5)) #define fix(x) ((double)(x)/QQ) int main() { double a = 128.0; int a_fix = fract(a); printf("a_fix: %d\n", a_fix); printf("2*a_fix: %d\n", 2*a_fix); // 輸出:512,已經溢出 return 0; }
因此,在使用定點數時,要注意定點數的整數和小數部分的位數,以免溢出。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/249627.html