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

运行前的文档:

运行后的结果输出:

原文地址:https://www.cnblogs.com/Jimmy1988/p/8120277.html

时间: 2024-10-16 19:05:29

python实现float/double的0x转化的相关文章

刨根问底:C++中浮点型变量(float, double)的比较问题。

首先,让我们先来看一段代码: #include <iostream> #include <iomanip> int main() { using namespace std; cout<<setprecision(17); float num1 = 1.1; double num2 = 1.1; if (num1 == num2) cout << "yes"<<endl; else cout << "no

【iOS】stringWithFormat 保留小数点位数 float double

以前就见过,如下: text = [NSString stringWithFormat:@"%.1f", percentageCompleted]; 但一直没在意.刚一时好奇,查了下,原来很简单: %.1f  表示小数点一位,%.2f 表示小数点2位,依次类推. 这篇文章 ios NSString format 保留小数点 float double 解释得很详细,我只参考了一小部分,有助!分享下!

关于c中 int, float, double转换中存在的精度损失问题

先看一段代码实验: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include<limits> #include<iostream> using namespace std; int main() {     unsigned int i = numeric_limits<unsigned int >::max();     float f = i;     unsigned

[C++] string与int, float, double相互转换

参考:http://blog.csdn.net/candadition/article/details/7342380 将string类型转换为int, float, double类型 主要通过以下几种方式: # 方法一: 使用stringstream stringstream在int或float类型转换为string类型的方法中已经介绍过, 这里也能用作将string类型转换为常用的数值类型. Demo: #include <iostream> #include <sstream>

解决java float double 浮点型参与计算失精度

本人前段时间做一个社区电商应用,发现了一个 天坑   ...................让我哭会 . 下面听听我的踩坑之路吧 ,电商肯定跟¥打交道了,计算少不了的.由于本人太菜 单纯的以为  float  double 可以直接参与加减乘除 感觉这种代码万无一失没去想这么多直接 float*int . 之前简单测试没问题,项目上线后自己偶然才发现的(不知道公司测试干嘛的) ,当选择多件商品时 , 还是直接说现象吧 比如 在代码中    0.1 f  * A         A为int 型  

python的float函数不常用方法汇总

>>> float('nan') nan >>> float('nan') == float('nan') False >>> float('Inf') inf >>> float('Inf') == float('inf') True >>> float('Inf') == float('nan') False >>> float('Inf') == 1 False >>> -f

MySQL中 DECIMAL FLOAT DOUBLE的区别

第一篇文章: MySQL中Decimal类型和Float Double等区别 MySQL中存在float,double等非标准数据类型,也有decimal这种标准数据类型. 其区别在于,float,double等非标准类型,在DB中保存的是近似值,而Decimal则以字符串的形式保存数值.float,double类型是可以存浮点数(即小数类型),但是float有个坏处,当你给定的数据是整数的时候,那么它就以整数给你处理.这样我们在存取货币值的时候自然遇到问题,我的default值为:0.00而实

python将PNG格式的图片转化成为jpg

python将PNG格式的图片转化成为jpg """ 先来说一下jpg图片和png图片的区别 jpg格式:是有损图片压缩类型,可用最少的磁盘空间得到较好的图像质量 png格式:不是压缩性,能保存透明等图 """ from PIL import Image import cv2 as cv import os def PNG_JPG(PngPath): img = cv.imread(PngPath, 0) w, h = img.shape[::-

C 语言实例 - 计算 int, float, double 和 char 字节大小。

使用 sizeof 操作符计算int, float, double 和 char四种变量字节大小. sizeof 是 C 语言的一种单目操作符,如C语言的其他操作符++.--等,它并不是函数. sizeof 操作符以字节形式给出了其操作数的存储大小. #include <stdio.h>int main(){    int integerType;    float floatType;    double doubleType;    char charType;    // sizeof