реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Как разобрать float на байты в pythone, Или подскажите алгоритм на С
mempfis_
сообщение Feb 20 2009, 12:32
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Добрый день.
Стоит задача разобрать float-число на байты и выполнить побайтную пересылку с помощью gprs-модема.
Задача осложнена тем что пишу на python-е и стандартный модуль struct, способный выполнить эту задачу, модемом не поддерживается.

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

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

Саму строку легко могу разбить на отдельные числа. А вот собрать с них float проблематично.
Подскажите пожалуйста где об этом можно почитать, может быть есть готовые алгоритмы на С (т.к. сомневаюсь что они есть на pythone)
Заранее спасибо за помощь smile.gif
Go to the top of the page
 
+Quote Post
Палыч
сообщение Feb 20 2009, 13:34
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(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);
Go to the top of the page
 
+Quote Post
rezident
сообщение Feb 20 2009, 14:00
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



IEEE 754 Converter
Go to the top of the page
 
+Quote Post
west329_
сообщение Feb 20 2009, 14:03
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 378
Регистрация: 10-09-07
Из: UKR/Voz
Пользователь №: 30 423



Не удивляйтесь только если код на 4К вырастет.
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Feb 20 2009, 15:34
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Спасибо всем за ответы smile.gif
Но мне не нужно то как это делается на С (я и сам могу написать используя библиотечные функции) smile.gif
Мне нужен алгоритм как число dec вручную переводится в float (напр. подпрограмма на С в которой всё делается без стандартных библиотек) .
Я пока что не понял как это вообще делается (удивительно по обратное преобразование (из float в dec) понял сразу).
Мне это преобразование нужно реализовать на питоне.
Думал может найдётся готовый пример чтобы по нему сделать свою функцию smile.gif
Go to the top of the page
 
+Quote Post
Палыч
сообщение Feb 21 2009, 10:14
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(mempfis_ @ Feb 20 2009, 18:34) *
Мне нужен алгоритм как число dec вручную переводится в float
А, что такое "число dec"? Вы, бы уж, конкретно бы указывали: что Вам нужно? Иначе: каков вопрос - таков ответ...
Хоть Вы и пытались уточнить свой вопрос, но понятьнее не стало... Вам что - нужно реализовать аналог функции atof() ? Это - почти так же, как atoi()... Во всяком случае - до точки. После точки - похоже, только вес цифр 0.1; 0.01; 0.001...
Go to the top of the page
 
+Quote Post
ukpyr
сообщение Feb 21 2009, 11:39
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 1 264
Регистрация: 17-06-08
Из: бандустан
Пользователь №: 38 347



что-то типа :
Код
f = float('0012.5000')
bytes = struct.pack('f', f)
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Feb 21 2009, 22:31
Сообщение #8


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Цитата(ukpyr @ Feb 21 2009, 14:39) *
что-то типа :
Код
f = float('0012.5000')
bytes = struct.pack('f', f)


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

Мне нужен пример на С или питоне для перевода строки в число типа float одинарной точности чтобы я мог его переделать в свою функцию которая могла бы вернуть мне 4 байта этого float-числа. Или хотябы понятное описание алгоритма перпевода десятичных дробных чисел в float. smile.gif
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 21 2009, 23:17
Сообщение #9


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(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;
}


И шо неясно ?
Go to the top of the page
 
+Quote Post
Andrew2000
сообщение Feb 22 2009, 00:36
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 421
Регистрация: 25-12-04
Пользователь №: 1 675



Что-то типа такого?

data = pack('F', 1.0)

f = unpack('F', data[0:4])
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Feb 23 2009, 10:59
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Ну вот разобрался в преобразовании чисел во 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')
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 07:52
Рейтинг@Mail.ru


Страница сгенерированна за 0.01484 секунд с 7
ELECTRONIX ©2004-2016