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

 
 
> Преобразование double во float
MKdemiurg
сообщение Aug 21 2013, 15:06
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 624
Регистрация: 15-06-10
Из: Россия
Пользователь №: 57 939



Собс-но сабж.
Есть число выдаваемое прибором формата DOUBLE.
При этом в компиляторе нет этого формата , а есть float и long int;
Как пересчисчитать с потерей точности и размерности?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 13)
flopix
сообщение Aug 21 2013, 15:55
Сообщение #2


Частый гость
**

Группа: Участник
Сообщений: 105
Регистрация: 21-06-12
Пользователь №: 72 429



А как же long float ?
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Aug 21 2013, 18:55
Сообщение #3


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



2ТС: что за компилятор?

Цитата(flopix @ Aug 21 2013, 19:55) *
А как же long float ?
Это однозначно что-то нестандартное.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
neiver
сообщение Aug 21 2013, 18:57
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123



Как-то так можно:
Код
float DoubleToFloat(const unsigned char *doublePtr)
{
    unsigned long long v = *(unsigned long long*)doublePtr;
    unsigned mantissa = (unsigned)((v & 0x003fffffffffffffull) >> (52 - 23));
    unsigned exponent = (unsigned)((v &  0x7ff0000000000000ull) >> 52);

    if(exponent > 1023 + 127)
        mantissa = 0x7fffffff;

    if(exponent < 1023 - 127)
        return 0.0;

    exponent -= 1023 - 127;
    exponent <<= 23;

    mantissa |= exponent;
    if(v & 0x8000000000000000ull)
        mantissa |= 0x80000000ul;
    union IntToFloat
    {
        unsigned i;
        float f;
    }iToF;
    iToF.i = mantissa;
    return iToF.f;
}

Только поаккуратней с этим кодом - я его быстро набрасал, толком не тестировал.
Go to the top of the page
 
+Quote Post
MKdemiurg
сообщение Aug 22 2013, 10:09
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 624
Регистрация: 15-06-10
Из: Россия
Пользователь №: 57 939



Спасибо за подсказки.
Сделал просто пересчётом по формулt из IEEE 754

unsigned long int r1, r2;
float r3;
r1=((((unsigned int)dob[0]&0x7F)<<4)|doub[1]>>4);
r2=(unsigned long int)doub[1]<<28|((unsigned long int)doub[2]<<20)|((unsigned long int)doub[3]<<12)|((unsigned long int)doub[4]<<4)|(doub[5]>>4);
r3=pow(-1,doup[0]>>7)*pow(2,(r1-1023))*(1+r2/4294967296.0);

PS Компилятр CVAVR - long long там тоже не реализован. Но до этого момента и не нужно было.
Go to the top of the page
 
+Quote Post
Xenia
сообщение Aug 22 2013, 11:21
Сообщение #6


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(MKdemiurg @ Aug 22 2013, 14:09) *
Компилятор CVAVR - long long там тоже не реализован. Но до этого момента и не нужно было.


Он и в этом моменте не нужен. Чтобы достать старшие байты double-числа, нет необходимости прибегать к типу long long. Более того, добычка этих байт через long long сопряжена с организацией огромных сдвигов (29 и 52 разрядов), что никак не назовешь эффективным программированием.

Было бы куда проще накладывать число double не на long long, а на unsigned char v[8] или unsigned short v[4], а затем сложить float из этих байт или слов. А еще симпатичнее вместо массива объявить структуру с битовыми полями под стать double-формату. Например:

Код
struct double_type {
   uint32_t mantissa_lo : 29;
   uint32_t mantissa_hi : 23;
   unsigned int exponent : 11;
   unsigned int sign : 1;
};

struct float_type {
   uint32_t mantissa : 23;
   unsigned int exponent : 8;
   unsigned int sign : 1;
};
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Aug 22 2013, 12:31
Сообщение #7


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Xenia @ Aug 22 2013, 15:21) *
Более того, добычка этих байт через long long сопряжена с организацией огромных сдвигов (29 и 52 разрядов), что никак не назовешь эффективным программированием.
Компилятор - не дурак, он не будет сдвигать по-битно 52 разаsm.gif
Поэтому никакой разницы в скорости вы не увидите, сравнивая с реализацией, использующей структуры.
Да читаемость исходников улучшиться, тут я не спорю. Но на некоторых архитектурах могут появятся проблемы с выравниваем и упаковкой...


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Xenia
сообщение Aug 22 2013, 13:10
Сообщение #8


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Если у компилятора нет формата double, то скорее всего, формата long long у него тоже нет. А "приживление" к нему формата long long ничем не проще, чем приживление формата double. Отсюда и вывод, что формат long long, как инструмент, здесь не годится.

Тогда как "мудрость" компилятора в отношении сдвига обычно сводится к вызову соответствующей библиотечной функции, писаной на ассемблере, которой число сдвигов задается в параметре.
Go to the top of the page
 
+Quote Post
MKdemiurg
сообщение Aug 22 2013, 13:21
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 624
Регистрация: 15-06-10
Из: Россия
Пользователь №: 57 939



Такс. Чото туплю.
От мантисы надо взять старшие 23 бита. Соответственно от экспоненты - младшие 8?
ЗЫ Таки да - формата long long тоже нет.
Go to the top of the page
 
+Quote Post
Xenia
сообщение Aug 22 2013, 13:28
Сообщение #10


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(MKdemiurg @ Aug 22 2013, 17:21) *
Такс. Чото туплю.
От мантисы надо взять старшие 23 бита. Соответственно от экспоненты - младшие 8?


Так я поэтому и поделила double-мантиссу на LO и HI, не аки как, а чтобы отделить от нее именно 23 старших бита (изначально в ней 52 бита, что в long не лезет).
Go to the top of the page
 
+Quote Post
MKdemiurg
сообщение Aug 22 2013, 13:30
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 624
Регистрация: 15-06-10
Из: Россия
Пользователь №: 57 939



Это понятно! А что с экспонентой то делать.
В дабле 11 бит, а во флоате - 8.

То что раньше делал - не влезает в long int результат умножения .
Пошёл по такому пути.

typedef struct
{
unsigned long int mantissa_lo : 29;
unsigned long int mantissa_hi : 23;
unsigned char exponent_lo : 4;
unsigned char exponent_hi : 7;
unsigned char sign : 1;
} double_format;

typedef struct {
unsigned long int mantissa : 23;
unsigned char exponent : 8;
unsigned char sign : 1;
}float_format;


union double_union
{
double_format dbl;
unsigned char b[8];
}dbl_union;

union float_union
{
float_format flt;
float F;
unsigned char b[4];
}flt_union;
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Aug 23 2013, 07:17
Сообщение #12


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Xenia @ Aug 22 2013, 17:10) *
Если у компилятора нет формата double, то скорее всего, формата long long у него тоже нет.
Не факт. В avr-gcc появился таки long-long, а double так и нет.

2ТС: чем скорее вы переползёте с CV на avr-gcc или IAR тем раньше сможете по-настоящему расправить свои крылья.
CV - это студенческая игрушка, пригодная лишь для ознакомления с миром ембеда и не более того.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
MKdemiurg
сообщение Aug 23 2013, 07:57
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 624
Регистрация: 15-06-10
Из: Россия
Пользователь №: 57 939



Проект запущен на CVAVR -надо допиливать. Рефакторить под IAR надо очень много.
С STM32 уже давно сижу на IAR
Go to the top of the page
 
+Quote Post
MKdemiurg
сообщение Aug 23 2013, 10:48
Сообщение #14


Знающий
****

Группа: Свой
Сообщений: 624
Регистрация: 15-06-10
Из: Россия
Пользователь №: 57 939



Таки реализовал.
Как в изначальном виде, только пришлось переделывать функцию возведения в степень.
--
Изза потери точности заинтересовался...А реально ли из дабла сделать просто текст в ASCII? Тем более временем выполнения я не лимитирован. Только размерностью переменных в 4 байта.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 14:31
Рейтинг@Mail.ru


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