博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python实现float/double的0x转化
阅读量:5818 次
发布时间:2019-06-18

本文共 3418 字,大约阅读时间需要 11 分钟。

1. 问题引出

最近遇到了一个小问题,即:

读取文本文件的内容,然后将文件中出现的数字(包括double, int, float等)转化为16进制0x存储

原本以为非常简单的内容,然后就着手去写了python,但是写着写着发现不对:

python貌似没办法直接读取内存数据;

因此不得不借助于C语言,这样又引出了python如何调用C lib

开始写c发现又有问题了:

int 类型的数据和float/double数据在内存中的存储方式是不同的

因此花了一些力气解决了这些问题,成功得将数字转化为了16进制0x的存储类型,特记录一下,以备后续查询,也可以让有需要的童鞋有个参考。

2. 基本知识

完成本实验前,你必须具备以下的基础知识:

1). float/double在内存中的存储方式

浮点数在内存中的存储形式为二进制的科学计数法,即

mark
mark
其中,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

简单起见,可参考该博客:

详细内容可参考python官方文档:

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
  • shared: 表示需要编译为动态库(.so)
  • Wl: 告诉编译器将后面的参数传递给链接器
  • soname: 指定了动态库的soname(简单共享名,Short for shared object name)

    更加详细的介绍可参考:

  • o : output,即要编译成目标文件的名字
  • fPIC: 地址无关代码(.so必须加此参数),详情可自行搜索

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. 运行结果

运行前的文档:
mark
运行后的结果输出:
mark

转载于:https://www.cnblogs.com/Jimmy1988/p/8120277.html

你可能感兴趣的文章
nginx反向代理配置及优化
查看>>
Office 365系列之十七:配置Outlook IMAP方式连接ExchangeOnline
查看>>
KMP算法的JavaScript实现
查看>>
在Windows 7下利用笔记本的无线网卡定义热区供手机上网
查看>>
均匀的生成圆和三角形内的随机点
查看>>
循环神经网络
查看>>
linux中serial driver理解【转】
查看>>
整理sqlserver 级联更新和删除 c#调用存储过程返回值
查看>>
ios32---线程的状态
查看>>
Android总结篇系列:Activity Intent Flags及Task相关属性
查看>>
读书笔记《集体智慧编程》Chapter 9 : Advanced Classification: Kernel Methods and SVMs
查看>>
React Native填坑之旅 -- 使用react-navigation代替Navigator
查看>>
在MVC中处理异常的总结
查看>>
DataReader方式 获取数据的操作
查看>>
influxdb入门——和mongodb一样可以动态增加字段
查看>>
我对大项目的看法(定义)
查看>>
phpmyadmin出现缺少mysqli扩展问题
查看>>
C#学习笔记——TCP通讯
查看>>
[转载]成为优秀程序员的10个有效方法
查看>>
SQL SERVER 与ACCESS、EXCEL的数据转换
查看>>