python实现float/double的0x转化
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 int
void 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)
更加详细的介绍可参考:http://blog.csdn.net/zhoujiaxq/article/details/10213655
- o : output,即要编译成目标文件的名字
- fPIC: 地址无关代码(.so必须加此参数),详情可自行搜索
III. python 代码
#!/usr/bin/python
import os
import ctypes
lib_name = './libftoc.so' #我自己的 c lib
filename = "rd.txt"
f1 = open(filename, 'r')
f2 = open('result.txt', 'w+')
#-----------------------------------
#check the number is float or not
def 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转化的更多相关文章
- Python之☞float浮点数精度问题
Python的浮点数损失精度问题(转) 一个简单的面试题: >>>0.1+0.1+0.1 0.2 >>>0.1+0.1+0.1 0.3000000000000000 ...
- QT中QString 与 int float double 等类型的相互转换
Qt中 int ,float ,double转换为QString 有两种方法 1.使用 QString::number(); 如: long a = 63; QString s = QString:: ...
- 关于c中 int, float, double转换中存在的精度损失问题
先看一段代码实验: #include<limits> #include<iostream> using namespace std; int main() { unsigned ...
- C语言中float,double类型,在内存中的结构(存储方式)
C语言中float,double类型,在内存中的结构(存储方式)从存储结构和算法上来讲,double和float是一样的,不一样的地方仅仅是float是32位的,double是64位的,所以doubl ...
- C++中将string类型转换为int, float, double类型 主要通过以下几种方式:
C++中将string类型转换为int, float, double类型 主要通过以下几种方式: # 方法一: 使用stringstream stringstream在int或float类型转换为 ...
- MySQL中Decimal类型和Float Double的区别 & BigDecimal与Double使用场景
MySQL中存在float,double等非标准数据类型,也有decimal这种标准数据类型. 其区别在于,float,double等非标准类型,在DB中保存的是近似值,而Decimal则以字符串的形 ...
- MySQL中 DECIMAL FLOAT DOUBLE的区别
第一篇文章: MySQL中Decimal类型和Float Double等区别 MySQL中存在float,double等非标准数据类型,也有decimal这种标准数据类型. 其区别在于,float,d ...
- 数据库类型空间效率探索(五)- decimal/float/double/varchar
以下测试为userinfo增加一列,列类型分别为decimal.float.double.varchar.由于innodb不支持optimize,所以每次测试,都会删除表test.userinfo,重 ...
- MySQL中Decimal类型和Float Double等区别
MySQL中存在float,double等非标准数据类型,也有decimal这种标准数据类型. 其区别在于,float,double等非标准类型,在DB中保存的是近似值,而Decimal则以字符串的形 ...
随机推荐
- Alwayson--使用证书创建高可用性组
--场景: --有服务器SQLNode11,SQLNODE21,SQLNODE31三台在同一故障转移群集SQLNode01中 --的数据库服务器,安装SQL SERVER 2012 并配置启动alwa ...
- jenkins常用插件汇总
jenkins常用插件汇总: Build-timeout Plugin:任务构建超时插件 Naginator Plugin:任务重试插件 Build User Vars Plugin:用户变量获取插件 ...
- CC2530学习路线-基础实验-GPIO 按键控制LED灯亮灭(2)
目录 1.前期预备知识 1.1 新大陆Zigbee模块按键电路图 1.2 CC2530相关寄存器 1.3 CC2530中断走向图 1.4 使用C语言为51单片机编写中断程序 1.5 *函数指针 2. ...
- 《Python绝技:运用Python成为顶级黑客》 用Python进行无线网络攻击
本章大部分代码都是实现了但是缺乏相应的应用环境,想具体测试的可以直接找到对应的环境或者自行修改脚本以适应生活常用的环境. 1.搭建无线网络攻击环境: 用Scapy测试无线网卡的嗅探功能: 插入无线网卡 ...
- BZOJ 1001--[BeiJing2006]狼抓兔子(最短路&对偶图)
1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 29035 Solved: 7604 Descript ...
- bonjour browser 下载
在Mac 上叫 Bonjour Browser http://www.macupdate.com/app/mac/13388/bonjour-browser/download IOS 上的 app 叫 ...
- spring JdbcTemplate批量插入以及单个插入时获取id
1. 批量更新插入 jdbcTemplate.batchUpdate(String sql, List<Object[]> batchArgs) Object[]数组的长度为每条记录的参数 ...
- OO第一单元作业
第一次作业 类图: 复杂度: 圈复杂度的问题一直困扰着这三次作业,主要体现在求导方法中先判断符号导致出现过多判断语句,应该将整理符号放在一个新的类中处理. 第一次作业由于对面向对象的思维有些不理解 ...
- 【LeetCode】462. 最少移动次数使数组元素相等 II
给定一个非空整数数组,找到使所有数组元素相等所需的最小移动数,其中每次移动可将选定的一个元素加1或减1. 您可以假设数组的长度最多为10000. 例如: 输入: [1,2,3] 输出: 2 说明: 只 ...
- laydata 点击日期闪现
因项目需求需要多个日期,然后点击日期就会出现闪现的情况,导致选择不了日期 html代码 <table class="form"> <tr> <th c ...