1. The problem arises
A small problem has recently been encountered, namely:
Read the contents of the text file, then convert the number appearing in the file (including double, int, float, etc.) to 16 binary 0x storage
Originally thought very simple content, then proceeded to write the python, but writes writes to find the wrong:
Python seems to have no way to read memory data directly ;
So we have to use the C language, which leads to how Python calls C lib.
Start writing C found another problem:
Data of type int and float/double data are stored in memory in different ways
So took some effort to solve these problems, the success of the digital conversion to 16 binary 0x
storage type, special record, for follow-up query, can also make the need for children's shoes have a reference.
2. Basic knowledge
Before completing this experiment, you must have the following basic knowledge:
1). How the float/double is stored in memory
Floating-point numbers are stored in memory in the form of a binary scientific notation, i.e.
where S is the symbol, p is the order code, and F is the mantissa
Its length is shown in the following table:
? |
Total length |
symbols |
Order Code |
Mantissa |
Float |
+ bit |
1 |
8 |
23 |
Double |
A bit |
1 |
11 |
52 |
sign bit S: 0 for positive, 1 for negative
Order Code bit P: for unsigned, the actual mantissa needs to be subtracted when calculating, 7F
that is, the actual calculationP=eb-0x7F
tail digit F: after the binary scientific calculation method, the previous constant is removed, 1
and only the binary data after the decimal point is retained.
Example 1:32bit binary into 0x42 0xOA 0x1A 0xA0
decimal floating-point number
Sign bit: The highest bit of s=0,0x42 is 0
Order code bit: 0x42<<1=0x84, 0x84-0x7f = 5
Number of digits: 0X0A1AA0 is converted to decimal and added 1 before the decimal point to get 1.0789375
Calculation:1.0789375*2^5 = 34.526
Example 2: Converting decimal 50.265 to 32-bit normalized floating-point number
N = 50.265
S = 0
N/2^p = 1.xxx, therefore, p=5
f=n/2^p=50.265/32=1.57078125
From the above:
Sign Bit s=0
EB = p+0x7f=0x84
Mantissa d[2]d[1]d[0]= 0x490f5c
So the end result is: 0x42490F5C
(remember that EB needs to be shifted OH)
2). How Python calls C Lib
For the sake of simplicity, refer to this blog: http://blog.csdn.net/golden1314521/article/details/44055523
For more information, refer to the official Python document: https://docs.python.org/2/library/ctypes.html
3. Code
I. C code: Read the memory address where float resides
/* *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. Compile this code for libftoc.so
gcc -shared -Wl,-soname,libftoc -o libftoc.so -fPIC ftoc.c
- Shared: Represents the need to compile into a dynamic library (. So)
- Wl: Tells the compiler to pass the following arguments to the linker
Soname: Specifies the soname of the dynamic library (simple share name, short for shared object name)
More detailed information can be found in: http://blog.csdn.net/zhoujiaxq/article/details/10213655
- O:output, which is the name to be compiled into the target file
FPIC: Address-independent code (. So must add this parameter), details can be searched by themselves
III. Python code
#!/usr/bin/pythonimport osimport ctypeslib_name = './libftoc.so ' #我自己的 c libfilename = "rd.txt" f1 = open (filename, ' R ') f 2 = 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 FL Oat 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.clos E ()
Vi. Running Results
Pre-run Documentation:
Output of the result after running:
Python for 0x conversion of float/double