標籤:tput cte uri 儲存方式 -fpic div tps else sdn
1. 問題引出
最近遇到了一個小問題,即:
讀取文字檔的內容,然後將檔案中出現的數字(包括double, int, float等)轉化為16進位0x儲存
原本以為非常簡單的內容,然後就著手去寫了python,但是寫著寫著發現不對:
python貌似沒辦法直接讀取記憶體資料;
因此不得不藉助於C語言,這樣又引出了python如何調用C lib
開始寫c發現又有問題了:
int 類型的資料和float/double資料在記憶體中的儲存方式是不同的
因此花了一些力氣解決了這些問題,成功得將數字轉化為了16進位0x的儲存類型,特記錄一下,以備後續查詢,也可以讓有需要的童鞋有個參考。
2. 基本知識
完成本實驗前,你必須具備以下的基礎知識:
1). float/double在記憶體中的儲存方式
浮點數在記憶體中的儲存形式為二進位的科學計數法,即
其中,S為符號,P為階碼,F為尾數
其長度如下表所示:
| ? |
總長度 |
符號 |
階碼 |
尾數 |
| float |
32 bit |
1 |
8 |
23 |
| double |
64 bit |
1 |
11 |
52 |
符號位 S: 0代表正數,1代表負數
階碼位 P: 為unsigned, 計算時候,需要將實際尾數減去7F, 即實際計算用的P=eb-0x7F
尾數位 F: 用二進位科學計演算法表示後,去掉前面的恒定1,只保留小數點後的位元據
例1:32bit二進位 0x42 0xOA 0x1A 0xA0 轉化為十進位浮點數
符號位:S=0,0x42的最高位為0
階碼位:0x42<<1=0x84, 0x84-0x7F = 5
尾數位:0x0A1AA0為換算為十進位然後小數點前加1得到1.0789375
計算:1.0789375*2^5 = 34.526
例2:將十進位數50.265轉化為32位規格化的浮點數
N = 50.265
S = 0
N/2^P = 1.xxx, 因此,P=5
F=N/2^P=50.265/32=1.57078125
由以上可知:
符號位S=0
eb = P+0x7F=0x84
尾數d[2]d[1]d[0]= 0x490F5C
因此,最終結果為:0x42490F5C (記住eb需要移位哦)
2). python如何調用C lib
簡單起見,可參考該部落格:http://blog.csdn.net/golden1314521/article/details/44055523
詳細內容可參考python官方文檔:https://docs.python.org/2/library/ctypes.html
3. 代碼
I. C 代碼:讀取float所在的記憶體位址
/* *Filename: ftoc.c */ #define uchar unsigned char#define uint unsigned intvoid ftoc(float fl, uchar arr[]) { void *pf; pf = &fl; uchar i; for(i=0; i<4; i++) { arr[i] = *((uchar *)pf+i); } return ;}
II. 編譯此代碼為libftoc.so
gcc -shared -Wl,-soname,libftoc -o libftoc.so -fPIC ftoc.c
III. python 代碼
#!/usr/bin/pythonimport osimport ctypeslib_name = ‘./libftoc.so‘ #我自己的 c libfilename = "rd.txt"f1 = open(filename, ‘r‘)f2 = open(‘result.txt‘, ‘w+‘)#-----------------------------------#check the number is float or notdef is_float(s): try: float(s) return True except ValueError: pass#-----------------------------------def ftoc(num): number = ctypes.c_float(num) #covert the python type to c type arr = ctypes.c_ubyte * 4 parr = arr(ctypes.c_ubyte(), ctypes.c_ubyte(), ctypes.c_ubyte(), ctypes.c_ubyte()) #create a c-type(unsigned char) array #access the c lib lib_ftoc = ctypes.CDLL(lib_name) #call the c lib function!!! #after this function, parr contains float‘s dec_number*4 lib_ftoc.ftoc(ctypes.c_float(num), parr) lst=[] for i in range(4): lst.append(parr[i]) lst[i] = hex(lst[i])[2:] #get rid of ‘0x‘ if(len(lst[i]) < 2): lst[i] = ‘0‘+lst[i] #make data 8-bit string = lst[3]+lst[2]+lst[1]+lst[0] string = string.upper() #uppercase the characters return string#============================================# main flow#===========================================lst = []line = f1.readline()while line: line.strip(‘\n‘) lst = line.split() for i in range(len(lst)): #if the number is digit if lst[i].isdigit(): lst[i] = hex(int(lst[i])) lst[i] = lst[i][2:] #get rid of ‘0x‘ lst[i] = lst[i].upper() if(len(lst[i]) < 8): lst[i] = ‘0‘*(8-len(lst[i])) + lst[i] #if the number is float else: if is_float(lst[i]): lst[i] = ftoc(float(lst[i])) for i in range(len(lst)): f2.write(lst[i]) f2.write(‘ ‘) f2.write(‘\n‘) line = f1.readline()f2.write(‘\n‘)f1.close()f2.close()
VI. 運行結果
運行前的文檔:
運行後的結果輸出:
python實現float/double的0x轉化