Float在內存中的存儲方式及IEC61131處理

Float在內存中的存儲方式及IEC61131處理

1,fp3232bits float)類型數據在存儲器中佔用4Bytes存儲,且遵循IEEE-754標準:編碼

一個浮點數分三部分組成:spa

符號位s(1bit: 31b)+指數e(8bits: 30-23b)+底數m(23bits: 22-0b)

2,符號位scode

Bit31表示符號位,符號位指數值的正負,0表示正數,1表示負數。blog

3,指數e內存

bit30-238bits表示一個有符號的指數,他是十進制指數加上127所得的 數值。it

因此咱們計算指數的時候必須減去127class

4,底數m循環

Bit22-023bits表示實際存儲的底數。二進制

底數實際佔用的是24bits的數據位,因爲最高位始終爲1,因此不顯式顯示。float

5,舉例

0.1

轉換爲二進制=0.00001

科學計數表示=1.0*2^-1

S=0

E=-1+127=126=0111 1110b

M=000 0000 _ 0000 0000 0000 0000

 0011 1111 0000 0000 _ 0000 0000 0000 0000

1.0

轉換爲二進制=1.0

科學計數表示=1.0*2^0

S=0

E=0+127=127=0111 1111b

M=000 0000 _ 0000 0000 0000 0000 

0011 1111 1000 0000 _ 0000 0000 0000 0000

3.0

轉換爲二進制=11.0

科學計數表示=1.1*2^1

S=0

E=1+127=128=1000 0000b

M=100 0000 _ 0000 0000 0000 0000 

0100 0000 0100 0000 _ 0000 0000 0000 0000

10.0

轉換爲二進制=1010.0

科學計數表示=1.01*2^3

S=0

E=3+127=130=1000 0010b

M=010 0000 _ 0000 0000 0000 0000 

0100 0001 0010 0000 _ 0000 0000 0000 0000

-10.0

轉換爲二進制=-1010.0

科學計數表示=-1.01*2^3

S=1

E=3+127=130=1000 0010b

M=010 0000 _ 0000 0000 0000 0000 

1100 0001 0010 0000 _ 0000 0000 0000 0000

1.625:

轉換爲二進制=1.101

科學計數表示=1.101*2^0

S=0

E=0+127=127=0x7F=0111 1111b

M=101 0000_0000 0000 0000 0000 

0011 1111 1101 0000_0000 0000 0000 0000

 

實際代碼操做中,咱們對fp32進行手動編碼操做的過程以下:

  • 考慮到0的特殊性,對0做單獨處理。
  • 非零值,底數均要轉化爲1.x * 2 ^e
  • 定義指數e=0;先把原始數據轉碼:

大於2的除2,直到小於2爲止,每次操做均要e++

小於1的乘2,直到大於1爲止,每次操做均要e--

  • 此時咱們已經取到了指數ee+127就是咱們指數域的數值了。

下面是取指的操做過程:

 1 (*    小於1不爲0的數據, 直接放大到>1        *)
 2 WHILE (real_data < 1.0) AND (real_data <> 0.0) DO
 3     real_data := real_data * 2.0;
 4     temp_E := temp_E - 1;
 5 END_WHILE;
 6 (*    大於2的數據, 直接縮小至<2                *)
 7 WHILE (real_data > 2.0) DO
 8     real_data := real_data / 2.0;
 9     temp_E := temp_E + 1;
10 END_WHILE;

temp_E就是咱們獲得的實際指數。 

  • 此時的底數爲1.x,因爲1固定不寫,因此咱們把小數部分0.x轉化爲二進制數值,左對齊,寫入到碼值的22..0數據域便可。
  • 循環體以小數碼值不爲0 與 數據域23bits寫滿做爲條件。
  • 小數部分每次乘2,記錄整數部分是否爲1,爲1的話當前對應的bit1
  • 更新小數部分的值,更新當前的置位位置。
  • 取整數的過程,須要考慮不一樣平臺的差別性,避免因爲四捨五入出錯。

 下面是我用IEE61131 ST編寫的取底數操做:

 

 1 (* 5, 計算底數, bit22..00                    *)
 2 int_pos := 22;                                            (* 第一個小數位的起始點    *)
 3 IF real_data <> 0.0 THEN
 4     real_dec := real_data - 1.0;
 5 ELSE
 6     real_dec := 0.0;
 7 END_IF;
 8 
 9 WHILE (real_dec > 0.0) AND (int_pos > -1) DO
10     real_tmp := real_dec * 2.0;
11     (* 判斷是不是1                            *)
12     real_int := REAL_TO_UDINT(real_tmp - 0.5);
13     IF real_int > UDINT#0 THEN
14         real_dec := real_tmp - 1.0;
15         temp_M   := temp_M + SHL_DWORD(DWORD#1, int_pos);
16     ELSE
17         real_dec := real_tmp;
18     END_IF;
19     int_pos := int_pos - 1;
20 END_WHILE;

 

temp_M就是最後計算的底數碼值。

6,解碼計算浮點過程是對上述操做的反向定義,相對比較容易寫。

7,咱們能夠分指數、整數和小數分別解析。

8,指數直接取出便可

1 (* 2, 解析指數: bit30..23            *)
2 t_E := DWORD_TO_INT(SHR_DWORD(UDINT_TO_DWORD(code32), 23) AND DWORD#16#FF);
3 IF t_E <> 0 THEN
4     t_E := t_E - 127;
5 END_IF;

 

9,整數部分

指數爲正的乘2累加,好比:1010

1 -> 1

0 -> 1*2+0=2

1 -> 2*2+1=5

0 -> 5*2+0=10

 

指數爲負的除2累加,結果累加到小數。

 

 1 (* 4, 計算整數部分數據                *)
 2 bTemp := t_E;
 3 IF bTemp < INT#0 THEN
 4     t_Int := UDINT#0;
 5     t_Dec := 1.0;
 6     WHILE bTemp < 0 DO
 7         bTemp := bTemp + 1;
 8         t_M   := t_M / UDINT#2;
 9         t_Dec := t_Dec / 2.0;
10     END_WHILE;
11 ELSE
12     t_Int := UDINT#1;
13     t_Dec := 0.0;
14     WHILE bTemp > 0 DO
15         t_Int := t_Int * UDINT#2;
16         IF (UDINT_TO_DWORD(t_M) AND DWORD#16#80000000) <> DWORD#0 THEN
17             t_Int := t_Int + UDINT#1;
18         END_IF;
19         bTemp := bTemp - 1;
20         t_M := t_M * UDINT#2;
21     END_WHILE;
22 END_IF;

 

10,小數部分除2累加,好比:101

1 -> 1/2=0.5

0 -> 0.5+0=0.5

1 -> 0.5+1/8=0.625

1 (* 4, 計算小數部分數據                *)
2 factor := 2.0;
3 WHILE t_M > UDINT#0 DO
4     IF (UDINT_TO_DWORD(t_M) AND DWORD#16#80000000) <> DWORD#0 THEN
5         t_Dec := t_Dec + 1.0 / factor;
6     END_IF;
7     factor := factor * 2.0;
8     t_M := t_M * UDINT#2;
9 END_WHILE;

 

11,最後根據符號位調整數值結果便可。

12,同時要注意的是碼值爲0的時候直接浮點爲0.0便可。

相關文章
相關標籤/搜索