程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> Vdsp(bf561)中的浮點運算(5):float類型表示總結

Vdsp(bf561)中的浮點運算(5):float類型表示總結

編輯:關於C++

1.1 float的疑問

寫一行很簡單的C代碼:

float a = 1234.56;

用vdsp編譯後的匯編代碼為:

R0 = 20972 ( X ) ;

R0.H = 17562 ;

[ FP + 0x10 ] = R0 ;

有點看不懂,呵呵,R0的值轉換為十六進制就是0x449A51EC。根據vdsp文檔的說法,其單精度浮點數格式為:

浮點數計算公式:

將0x449A51EC轉換為二進制:

0100 0100 1001 1010 0101 0001 1110 1100

可得:

Sign = 0

Mantissa = 001 1010 0101 0001 1110 1100

Exponent = 1000 1001

按照公式

將Exponent轉換為十進制,其值為137。

將Mantissa轉換為十進制,其值為:

2-3 + 2-4 + 2-6 + 2-9 + 2 -11 + 2-15 + 2-16 + 2-17 + 2-18 + 2-20 + 2-21 =

0.125 + 0.0625 + 0.015625 + 0.001953125 + 0.00048828125 + 0.000030517578125 + 0.0000152587890625 + 0.00000762939453125 + 0.000003814697265625 + 0.00000095367431640625 + 0.000000476837158203125 = 0.205625057220458984375

代入浮點數計算公式:

(-1)0 + 1. 205625057220458984375 * 2 (137-127)

= 1234.56005859375

那麼編譯器又是如何將1234.56轉換為0x449A51EC的呢?

首先轉換整數部分,用2除,取余數,其結果為:

1234 / 2 = 617 ….. 0

617 / 2 = 308 …….1

308 / 2 = 154 …….0

154 / 2 = 77 ……...0

77 / 2 = 38 ……….1

38 / 2 = 19 ……….0

19/ 2 = 9 ………….1

9 / 2 = 4………… .1

4/ 2 = 2 …………..0

2/2 = 1……………0

1/2 = 0……………1

即100 1101 0010,用16進制表示則為:0x4d2。

再轉換小數部分,用2乘,取整數位:

0.56 * 2 = 1.12取1

0.12 * 2 = 0.24取0

0.24 * 2 = 0.48取0

0.48 * 2 = 0.96取0

0.96 * 2 = 1.92取1

0.92 * 2 = 1.84取1

0.84 * 2 = 1.68取1

0.68 * 2 = 1.36取1

0.36 * 2 = 0.72取0

0.72 * 2 = 1.44取1

0.44 * 2 = 0.88取0

0.88 * 2 = 1.76取1

0.76 * 2 = 1.52取1

小數部分的值為0.1000 1111 0101 11

所以1234.56表示成二進制數就是

100 1101 0010. 1000 1111 0101 11

由於浮點數表示法的尾數部分以1開頭,所以上面的這個數可以表示為:

1.00 1101 0010 1000 1111 0101 11 * 210

從浮點數的表示公式即可算出

Exponent = 127 + 10 = 137

而尾數部分則為

00 1101 0010 1000 1111 0101 11

因此整個數就是:

0      1000 1001   00 1101 0010 1000 1111 0101 11

符號位    指數          尾數

從整數的角度來看就是:

0100 0100 1001 1010 0101 0001 1110 1011

十六進制表示為:

4    4    9    A   5    1   E    B

奇怪得很,最後居然有偏差。莫非VDSP還有什麼機關不成?

1.2 FLT_MIN

FLT_MIN是在float.h中定義的一個常量,用以表示單精度浮點數的最小值。

#define FLT_MIN  1.1754943508222875E-38F

那麼這個值從何而來?

從浮點數的表示可以知道,尾數必然是大於等於1的,要取最小值,只能將指數設置為最小值,由於浮點數規定將指數為0的情況表示特殊的浮點數,因此指數只能取1,即

0      00000001   00000000000000000000000

符號位    指數     尾數

從16進制整數看它的值就是 0x00 80 00 00。

根據浮點數的計算公式可知這個值為:

1.0 * 2-126

= 1.1754943508222875079687365372222e-38

這個是計算器的計算結果。

1.3 FLT_MAX

FLT_MAX是在float.h中定義的一個常量,用以表示單精度浮點數的最大值。

#define FLT_MAX 3.4028234663852886E+38F

那麼這個值從何而來?

從浮點數的表示可以知道,要取最大值,可以將指數和尾數都設置為最大值,由於標准規定將指數全為1留做特殊表示,故指數最大值為255,這個數即

0      11111110   11111111111111111111111

符號位    指數     尾數

從16進制整數看它的值就是 0x7f 7f ff ff。

根據浮點數的計算公式可知這個值為:

1. 9999997615814208984375 * 2(254-127)

= 3.4028234663852886E+38

這個是計算器的計算結果。

1.4 FLT_EPSILON

FLT_EPSILON是在float.h中定義的一個常量,用以表示一個單精度浮點數的最小分辨率,文檔對此值的描述是:

A constant that represents the smallest value that may added to 1.0 and still result in a change of value (for example, FLT_EPSILON)

也就是加1後要能看得出變化!

FLT_EPSILON定義為:

#define FLT_EPSILON  1.1920928955078125E-07F

那麼這個值從何而來?

先看1.0的浮點表示:

0      01111111   00000000000000000000000

符號位    指數     尾數

從十六進制的角度看就是0x3f80 0000

要想把這個值加上一個足夠小的值但仍然能看出變化,當然就是把尾數直接加1,這個數即2-23,轉換成十進制就是FLT_EPSILON的值。

下面是一個很有意思的問題:

float a = FLT_EPSILON;

這個時候a的值會是什麼?

在VDSP下試了一下,a的值看成整數是:0x3400 0000,也就是:

0      01101000   00000000000000000000000

符號位    指數     尾數

即1.0 x 2(104-127) = 1.0 x 2-23

1.5 INF和NAN

IEEE754規定了單精度浮點數的類型:

Type Exponent Fraction Value NAN 255 Nonzero Undefined Infinity 255 0 (–1)s Infinity Normal 1 <= e <= 254 Any (–1)s (1.f22-0) 2 e–127 Zero 0 0 (–1)s Zero

INF的表示要求指數為255,尾數為0,即:

0        11111111   00000000000000000000000

符號位    指數     尾數

也就是0x7f80 0000。

在VDSP下可以用:

float a = 1.0 / 0.0;

來生成一個INF的數。

當然,符號位也可以取負數,即:

1      11111111   00000000000000000000000

符號位    指數     尾數

也就是0xff80 0000。

在VDSP下可以用:

float a = -1.0 / 0.0;

來生成一個-INF的數。

上述兩個INF都可以用isinf函數來檢測它。

NAN的表示要求指數為255,尾數不為0,即:

0      11111111   00000000000000000000001

符號位    指數     尾數(可取任意不為0的值)

也就是0x7f80 0001這樣的數。

在VDSP下可以用:

float a = 0.0 / 0.0;

來生成一個NAN的數,不過這個時候它的值為0xffff ffff。

可以使用isnan函數來檢測它。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved