Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как разобрать float на байты в pythone
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
mempfis_
Добрый день.
Стоит задача разобрать float-число на байты и выполнить побайтную пересылку с помощью gprs-модема.
Задача осложнена тем что пишу на python-е и стандартный модуль struct, способный выполнить эту задачу, модемом не поддерживается.

Поэтому прошу помочь алгоритмом преобразования строки содержащей float-число в 4 байта этого самого float-числа.

Т.е. параметр будет строка вида '0012.5000' а результат 11000001 01001000 00000000 00000000b = C1 48 00 00h

Саму строку легко могу разбить на отдельные числа. А вот собрать с них float проблематично.
Подскажите пожалуйста где об этом можно почитать, может быть есть готовые алгоритмы на С (т.к. сомневаюсь что они есть на pythone)
Заранее спасибо за помощь smile.gif
Палыч
Цитата(mempfis_ @ Feb 20 2009, 15:32) *
может быть есть готовые алгоритмы на С

Сомневаюсь, что для такой задачи требуется некий алгоритм... Процедура преобразования будет иметь, примерно, такой вид
Код
void Convert(char *Str, void *pCh)
{
   float F;
   sscanf(Str, "%f", &F);
   *(float *)pCh= F;
}


Вызов этой процедуры будет, приметно, такой
Код
  unsigned char mCh[4];
   ......
   Convert("0012.5000", mCh);


PS. Можно процедуру записать ещё проще
Код
void Convert(char *Str, void *pCh)
{
    sscanf(Str, "%f", pCh);
}
Поскольку внутренность процедуры сократилась до одной строки - её можно совсем сократить
Код
  unsigned char mCh[4];
   ......
   sscanf("0012.5000", "%f", mCh);
rezident
IEEE 754 Converter
west329_
Не удивляйтесь только если код на 4К вырастет.
mempfis_
Спасибо всем за ответы smile.gif
Но мне не нужно то как это делается на С (я и сам могу написать используя библиотечные функции) smile.gif
Мне нужен алгоритм как число dec вручную переводится в float (напр. подпрограмма на С в которой всё делается без стандартных библиотек) .
Я пока что не понял как это вообще делается (удивительно по обратное преобразование (из float в dec) понял сразу).
Мне это преобразование нужно реализовать на питоне.
Думал может найдётся готовый пример чтобы по нему сделать свою функцию smile.gif
Палыч
Цитата(mempfis_ @ Feb 20 2009, 18:34) *
Мне нужен алгоритм как число dec вручную переводится в float
А, что такое "число dec"? Вы, бы уж, конкретно бы указывали: что Вам нужно? Иначе: каков вопрос - таков ответ...
Хоть Вы и пытались уточнить свой вопрос, но понятьнее не стало... Вам что - нужно реализовать аналог функции atof() ? Это - почти так же, как atoi()... Во всяком случае - до точки. После точки - похоже, только вес цифр 0.1; 0.01; 0.001...
ukpyr
что-то типа :
Код
f = float('0012.5000')
bytes = struct.pack('f', f)
mempfis_
Цитата(ukpyr @ Feb 21 2009, 14:39) *
что-то типа :
Код
f = float('0012.5000')
bytes = struct.pack('f', f)


Да этот модуль мне подходит но он не поддерживается интерпретатором питона gprs-модема (я об этом написал в самом первом посте это и послужило поводом для создания темы) crying.gif

Мне нужен пример на С или питоне для перевода строки в число типа float одинарной точности чтобы я мог его переделать в свою функцию которая могла бы вернуть мне 4 байта этого float-числа. Или хотябы понятное описание алгоритма перпевода десятичных дробных чисел в float. smile.gif
_Pasha
Цитата(mempfis_ @ Feb 22 2009, 01:31) *
для перевода строки в число типа float одинарной точности
Код
#include <stdlib.h>
volatile float f;
char s[] = "2.4137";
int main (void)
{
f = atof(s);
return 0;
}


И шо неясно ?
Andrew2000
Что-то типа такого?

data = pack('F', 1.0)

f = unpack('F', data[0:4])
mempfis_
Ну вот разобрался в преобразовании чисел во float и написал свой скрипт на питоне для перевода строки 'xxxx.yyyy' в 4 байта соответствующие float-числу одинарной точности.
Для контроля правильности преобразования использовал функцию pack из модуля struct.
Может кто что посоветует в плане оптимизации.
Функция принимает строку - знак, 4-5 знаков целой части, 4-5 знаков дробной части, переводит их в 4 байта и возвращает их.
Обработку ошибок не провожу.
Вобщем буду благодарен любой критике smile.gif

P.S. Для тех кто захочет сказать 'А нафиг это надо если есть модуль struct' ещё раз повторяю ИНТЕРПРЕТАТОР ПИТОНА GPRS-МОДЕМА НЕ ПОДДЕРЖИВАЕТ МОДУЛЬ STRUCT (в отличии от компилятора О_о )

CODE
import struct

def strToFloat(string):
#для контроля преобразования строки во флоат используем функци. pack из модуля struct
res = struct.pack('f', float(string))
dd3 = hex(ord(res[3]))
dd2 = hex(ord(res[2]))
dd1 = hex(ord(res[1]))
dd0 = hex(ord(res[0]))
#print dd3, dd2, dd1, dd0

#ищем указатели на знак и точку
psighn = string.find('-')
ppoint = string.find('.')

#определяем знак мантиссы, выделяем целу. и дробну. часть
sighn = 0
integer = 0
fract = 0
if(psighn != -1):
sighn = 1
integer = string[1:ppoint]
else:
integer = string[:ppoint]
fract = string[ppoint+1:]+'0'
#print 'integer=', integer
#print 'fract=', fract


#определяем сколько бит занимает целая часть числа
int_data = int(integer, 10)
int_bit = 0
mask = 0x800000
if(int_data > 0):
for int_bit in range(0,24,1):
if((int_data & mask) == 0):
mask = mask >> 1

else:
int_bit = 23 - int_bit
#print 'MSB position =',int_bit
break

#print 'num of bits=',int_bit

#формируем смещённый показатель степени и добавляем его до флоат-числа
power = 127 + int_bit
#print 'power=',power
float_data = (power<<23)
#print 'float_data=',hex(float_data),'\n'

#добавляем до флоат-числа целу. часть без старшего единичного бита
#зануляем старший бит
temp = int_data&(~(2**int_bit))
#print temp
#добавляем целу. часть
float_data = float_data | (temp*(2**(23-int_bit)))
#print float_data

#определяем сколько бит осталось для дробной части
fract_bit = 23-int_bit
#print fract_bit

#само дробное число
fract_data = int(fract, 10)
#print fract_data

#определяем порядок числа
val = 0
if((fract_data > 0) and (fract_data <= 10)):
val = 10
elif((fract_data > 10) and (fract_data <= 100)):
val = 100
elif((fract_data > 100) and (fract_data <= 1000)):
val = 1000
elif((fract_data > 1000) and (fract_data <= 10000)):
val = 10000
elif((fract_data > 10000) and (fract_data <= 100000)):
val = 100000
#print val

#формируем дробну. часть числа
fract_float = 0
for k in range(0,fract_bit,1):
fract_data = fract_data*2
fract_float = fract_float << 1
if(fract_data >= val):
fract_data = fract_data-val
fract_float = fract_float|0x1
#print k
#print hex(fract_float)
#print fract_float

fract_data = fract_data*2
if(fract_data >= val):
fract_float = fract_float|0x1

#присоединяем дробну. часть к всему числу
float_data = float_data|fract_float
#print float_data
result=[0,0,0,0]
result[3]=0
if(sighn == 1):
result[3] = 0x80
result[3] = result[3]|(float_data>>24)&0xff
result[2] = (float_data>>16)&0xff
result[1] = (float_data>>8)&0xff
result[0] = (float_data)&0xff

print '\nethalon=', dd3, dd2, dd1, dd0
print 'my func=', hex(result[3]),hex(result[2]),hex(result[1]),hex(result[0])
return result

strToFloat('-25123.456')
strToFloat('1025.23')
trToFloat('36511.99')
strToFloat('23999.9988')
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.