IEEE-754标准(32位) 十六进制转换十进制浮点数
因實驗需要,讀取陀螺儀的數據是16進制的數據,需要將該數據轉化為10進制方便自己查看,理解。記錄如下:
1.將(32位)16進制IEEE-754標準浮點數就是用十六進制表示浮點,稱為單精度浮點數。
?float類型在內存中占4個字節(32位),最高位用于表示符號;在剩下的31位中,從右向左了8位用于表示指數,其余用于表示尾數。(一個字節是8位)
對應關系如下:
符號位????指數位????尾數位
1位???????8位???????23位
舉例:(1)IEEE-754標準浮點數表示為 404FC593 H(H表示是16進制;)
(2)已知一個數為2.5,IEEE-754標準浮點數表示為 40200000H。
16進制浮點數與十進制的轉化步驟:
1、轉換為二進制 0 10000000 10011111100010110010011
2、其第0位 為符號位,為0則表示正數,反之1為復數,其讀數值用 s 表示;
3、第1~8位為冪數,其讀數值用 e 表示;
4、第9~31位共23位作為系數,視為二進制純小數,假定該小數的十進制值為 x ;
則按照規定,該浮點數的值用十進制表示為:= (-1)^s * (1 + x) * 2^(e - 127)
2.冪數的計算
10000000 轉換為十進制 128
3.系數的計算
二進制對應的位數的數*2的負位置,再相加
10011111100010110010011
1 1 * 2^(-1)
0 0 * 2^(-2)
0 0 * 2^(-3)
1 1 * 2^(-4)
... ...
1 1 * 2^(-23)
相加可得
0.62321698665618896
4.十進制最后換算
(-1)^0 * (1+ 0.62321698665618896) * 2^(128-127) = 3.246433973312378
舉例:
16進制浮點數與十進制的轉化步驟:
對于大小為32-bit的浮點數(32-bit為單精度,64-bit浮點數為雙精度,80-bit為擴展精度浮點數),
1、其第31 bit為符號位,為0則表示正數,反之為復數,其讀數值用s表示;
2、第30~23 bit為冪數,其讀數值用e表示;
3、第22~0 bit共23 bit作為系數,視為二進制純小數,假定該小數的十進制值為x;
則按照規定,該浮點數的值用十進制表示為:= (-1)^s * (1 + x) * 2^(e - 127)
例如:對于16進制浮點數49E48E68H來說,如圖5:
1、其第31 bit為符號位,為0則表示為正數;(左邊是高位,右邊是低位)
2、第30~23 bit依次為100 1001 1,讀成十進制就是147,即e = 147。
3、第22~0 bit依次為110 0100 1000 1110 0110 1000,也就是二進制的純小數0.110 0100 1000 1110 0110 1000,其十進制形式為0.78559589385986328125,即x = 0.78559589385986328125。即x = 0.78559589385986328125。
可知:16進制浮點數49E48E68H的10進制表示:
=(-1)^s * (1 + x) * 2^(e - 127)
=(-1)^0 * (1+ 0.78559589385986328125) * 2^(147-127) = 1872333。
下面是實現的代碼如下所示:
#include <stdio.h>
#include <math.h>
//十六進制數轉浮點數通用方法
float Hex2Float(unsigned long number)
{unsigned int sign = (number & 0x80000000) ? -1 : 1;//三目運算符unsigned int exponent = ((number >> 23) & 0xff) - 127;//先右移操作,再按位與計算,出來結果是30到23位對應的efloat mantissa = 1 + ((float)(number & 0x7fffff) / 0x7fffff);//將22~0轉化為10進制,得到對應的xreturn sign * mantissa * pow(2, exponent);
}
//測試用例
int main()
{unsigned long a = 0x404FC593;//16進制404FC593float result = Hex2Float(a);printf("result = %f \n", result);return 0;
}
結果如下:
代碼解讀:(下邊number以49E48E68為例:)
? ??
(1)首先將number與16進制的8000 0000 做按位與預算,因為16進制8000 0000的二進制除了32位是1之外其他都是0(任何數與0按位與都是0),所以按位與計算是為了得到符號位。
按位與操作規則:?按位與操作 0&0=0; 0&1=0; 1&0=0; 1&1=1
再進行三目運算符操作:括號內表達式非0的話就取-1,是0的話就取1。最終得到符號位。
C語言三目運算符用法:
對于條件表達式b ? x : y,先計算條件b,然后進行判斷。如果b的值為true,計算x的值,運算結果為x的值;否則,計算y的值,運算結果為y的值。
(2)右移操作:https://blog.csdn.net/weixin_42216574/article/details/82885102
?左移運算符(<<)
-
將一個運算對象的各二進制位全部左移若干位(左邊的二進制位丟棄,右邊補0)。
-
例:a = a << 2 將a的二進制位左移2位,右補0,
-
左移1位后a = a * 2;
-
若左移時舍棄的高位不包含1,則每左移一位,相當于該數乘以2。
右移運算符(>>),此處右移23位
-
將一個數的各二進制位全部右移若干位,正數左補0,負數左補1,右邊丟棄。
-
操作數每右移一位,相當于該數除以2。
- 例如:a = a >> 2 將a的二進制位右移2位,
左補0 or 補1 得看被移數是正還是負。
- 例如:a = a >> 2 將a的二進制位右移2位,
-
>> 運算符把 expression1 的所有位向右移 expression2 指定的位數。expression1 的符號位被用來填充右移后左邊空出來的位。向右移出的位被丟棄。
- 例如,下面的代碼被求值后,temp 的值是 -4:
var temp = -14 >> 2
-14 (即二進制的 11110010)右移兩位等于 -4 (即二進制的 11111100)。
- 例如,下面的代碼被求值后,temp 的值是 -4:
-
無符號右移運算符(>>>)
-
>>> 運算符把 expression1 的各個位向右移 expression2 指定的位數。右移后左邊空出的位用零來填充。移出右邊的位被丟棄。
所以上述右移23位之后得到:
0000? 0000? 0000 0000? 0000 0000 1001 0011
右移完成之后再與16進制0xff做按位與運算。ff的二進制是(11111111),
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 |
按位與:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?1? ?1? ?1? ? 1? ? 1? ? 1? ? 1? ? 1
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 得到:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ????1? ?0? ?0? ? 1? ?0? ?0? ? 1? ? 1? ? ?
此步驟得到的就是1到8位,對應第二步。
? ( 3)再與0x7fffff做按位與運算。
?
------------------------------------------上邊的代碼對應的無符號數據,下邊是可以是有符號的:(使用的是unsigned long long 型,因為要考慮數據范圍)
char,short ,int ,long,long long,unsigned long long數據范圍
速查表:
char -128 ~ +127 (1 Byte)
short -32767 ~ + 32768 (2 Bytes)
unsigned short 0 ~ 65535 (2 Bytes)
int -2147483648 ~ +2147483647 (4 Bytes)
unsigned int 0 ~ 4294967295 (4 Bytes)
long == int
long long -9223372036854775808 ~ +9223372036854775807 (8 Bytes)
double 1.7 * 10^308 (8 Bytes)
unsigned int 0~4294967295
long long的最大值:9223372036854775807
long long的最小值:-9223372036854775808
unsigned long long的最大值:18446744073709551615
__int64的最大值:9223372036854775807
__int64的最小值:-9223372036854775808
unsigned __int64的最大值:18446744073709551615
#include <stdio.h>
#include <math.h>
#include <iostream>//十六進制數轉浮點數通用方法
float Hex2Float(unsigned long long number)
{std::cout << "number:" << number << std::endl;int sign = (number & 0x80000000) ? -1 : 1;//符號位std::cout << "符號位:" << sign << std::endl;int exponent = ((number >> 23) & 0xff) - 127;std::cout << "e位:" << exponent << std::endl;float mantissa = 1 + ((float)(number & 0x7fffff) / 0x7fffff);std::cout << "x位:" << mantissa <<std::endl;return sign * mantissa * pow(2, exponent);
}
//測試用例
int main()
{unsigned long long a = 0xBEAA2737;float result = Hex2Float(a);printf("result = %f \n", result);return 0;
}
結果是:
下面是參考另外一位博主的直接由32位的二進制轉化為10進制:
https://blog.csdn.net/qq_35353824/article/details/107773420#comments_14315438
IEEE-754標準(32位)十六進制轉十進制浮點數(其實下面第一個程序直接輸入的是二進制數)
#include<fstream>
#include <sstream>
#include <iostream>
#include<math.h>
using namespace std;double BtoD(string x)
{double ans;int E = 0;double D = 0;for (int i = 1; i < 32; i++){if (i < 9){E += (x[i] - '0') << (8 - i);//cout << E << endl;}else{D += (x[i] - '0') * pow(2 ,(8 - i));//cout << D << endl;}}ans = pow(2, E - 127)*(1+D);if (x[0] = '1')ans = -ans;return -ans;
}int main()
{string input;ifstream in;in.open("D:\\p1.txt");if (!in.good()){cout << "文件打開失敗" << endl;system("pause");return 0;}while (!in.eof()){in >> input;cout << input << endl;;cout << BtoD(input) << endl;system("pause");}in.close();cout << "轉換完成" << endl;system("pause");return 0;}
十進制浮點數 轉IEEE-754標準(32位)十六進制:
#include<iostream>
#include<vector>
#include"math.h"
#include<iomanip>
#include <fstream>using namespace std;vector<bool> zhengshu;//存整數部分的二進制
vector<bool> xiaoshu;//存小數部分的二進制vector<bool> get_zhengshu_2b(float a)
{vector<bool> x;x.clear();//八位二進制a xxxx xxxx與1000 0000與,得到每位的二進制數for (int i = 0; i < 8; i++){if ((((int)a)&(0x80 >> i))){x.push_back(1);}else{x.push_back(0);}}return x;
}void get_2b(float a)
{//獲取整數部分的二進制碼float fabs_a = fabs(a);//取絕對值zhengshu.clear();xiaoshu.clear();zhengshu = get_zhengshu_2b(fabs_a);//獲取小數部分的二進制碼float n = 2; //小數位的階數取倒數float b = (fabs_a - floor(fabs_a));//每次除以2判斷該位是0還是1while (!b == 0){if ((1.0 / n) < b){xiaoshu.push_back(1);//若為1則b減去該位所對應的十進制小數大小 ,繼續判斷低一位,直到b=0b = b - (1.0 / n);}else if ((1.0 / n) > b){xiaoshu.push_back(0);}else if ((1.0 / n) == b){xiaoshu.push_back(1);break;}n = n * 2;}
}
int get_jiema() //返回階碼
{for (int i = 0; i < 8; i++){if (zhengshu[i] == 1)//判斷從左邊起第一個為1的位置return 7 - i; // 返回階碼大小}
}
vector<bool> get_yima()//得到移碼
{int e = get_jiema();e = e + 127; //階碼偏移得到移碼return get_zhengshu_2b(e);//返回獲得的移碼的二進制形式
}
vector<bool> get_weima()//獲得尾碼
{vector <bool> m;//小數的二進制前插入規格化的碼得到尾碼xiaoshu.insert(xiaoshu.begin(), zhengshu.begin() + (8 - get_jiema()), zhengshu.end());m = xiaoshu;return m;
}
vector<bool> to_IEEE754(float x)
{vector<bool> IEEE;IEEE.clear();get_2b(x); //得到x的二進制碼/*//輸出原數的二進制形式cout << "絕對值的二進制數為:" << endl;for (int i = 0; i < zhengshu.size(); i++){cout << zhengshu[i];}cout << ".";for (int i = 0; i < xiaoshu.size(); i++){cout << xiaoshu[i];}cout << endl;//輸出移碼cout << "移碼為:" << endl;vector<bool> E = get_yima();for (int i = 0; i < 8; i++){cout << E[i];}cout << endl;*///組合成短浮點數代碼:vector<bool> yima;yima.clear();yima = get_yima();vector<bool> weima;weima.clear();weima = get_weima();if (x > 0)//判斷并添加符號位{IEEE.insert(IEEE.end(), 1, 0);}else{IEEE.insert(IEEE.end(), 1, 1);}IEEE.insert(IEEE.end(), yima.begin(), yima.end());//添加移碼IEEE.insert(IEEE.end(), weima.begin(), weima.end());//添加尾碼IEEE.insert(IEEE.end(), 32 - 9 - weima.size(), 0);//尾部補零 共32位return IEEE;
}
void get_hex(vector<bool> E)//得到十六進制顯示
{ofstream out;out.open("D:\\Desktop\\輸出.txt", ios::app);vector<bool>::iterator ite = E.begin();//迭代器int sum = 0;int n = 8;while (n--)//八組循環{for (int i = 0; i < 4; i++)//求每4位的十六進制表示{sum = sum + (*ite)*pow(2, 3 - i);//8 4 2 1ite++;}cout << setiosflags(ios::uppercase) << hex << sum;//16進制大寫字母輸出out << setiosflags(ios::uppercase) << hex << sum;// 寫入文件sum = 0;}out << endl;out.close();cout << endl;
}int main()
{ifstream in;in.open("D:\\P1.txt");//求十進制的短浮點數代碼//if (!in.good()){cout << "文件打開失敗" << endl;system("pause");return 0;}while (!in.eof()){float x;vector<bool> IEEE;in >> x;cout << x <<"轉換為:" ;IEEE = to_IEEE754(x);get_hex(IEEE);IEEE.clear();cout << endl;//system("pause");}in.close();cout << "轉換完成" << endl;system("pause");return 0;}
?
總結
以上是生活随笔為你收集整理的IEEE-754标准(32位) 十六进制转换十进制浮点数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PCL:点云配准1、基础知识:平面3自由
- 下一篇: PCL点云处理算法目录