Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как заполнить структуру дробного числа? 
:(
    Опции темы
kiLLProg
Дата 15.4.2011, 15:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 1.10.2008

Репутация: нет
Всего: нет



Здравствуйте. Пишу программу на чистом Си. Есть структура, которая описывает представление в памяти ЭВМ дробное число float по стандарту IEEE 754.
Код

#include <stdio.h>

union ParsedFloat
{
      float v;                 // значение
       struct
       {
           unsigned int m : 23; // мантисса
           unsigned int e : 8;  // показатель степени
           unsigned int s : 1;  // знак
      } f;
};

int main()
{
     union ParsedFloat pf;

     pf.f.m = 0x48F5C3;
     pf.f.e = 0x80;
     pf.f.s = 0;
    
     printf("%f", pf.v);  // 3.14

     getchar();
}

На выходе значение будет: 3.14

А вот когда байты дробного числа (точнее, байты представления дробн. числа в памяти ЭВМ) содержатся в переменной типа int (0x4048F5C3), то у меня не получатся правильно вытащить их. Точнее сказать, я не могу вытащить мантиссу.

С вытаскиванием знака и порядка я вроде справился.
Код

// В этом куске я может, ошибаюсь, но  не важно. Со знаком справиться - дело нехитрое. 
if (c & 1)  // Есть знаковый бит? 
     pf.f.s = 1;  // Да
   else
     pf.f.s = 0;  // Нет знакового бита
//==========

//получаем порядок
unsigned char a1=0;
int tmp;
int c = 0x4048F5C3;
   
   tmp = c;
   tmp = tmp >> 23;
   a1 = tmp;
   
   pf.f.m = 0x48F5C3;
   pf.f.e = a1; 
   pf.f.s = 0;

   f1 = pf.v;  // f1 = 3.14

А вот с мантиссой проблемы. Мне нужны только 23 бита из 24х (24 бита = 3 байта (48F5C3)).
48F5C3 = 10010001111010111000011 (23 бита) + еще один ноль появится, когда это число, например, по массиву раскидаем. И этот ноль мне не нужен. Вот как я понимаю свою проблему.

Пробовал делать так.
Код

char mas[] = {0x40, 0x48, 0xF5, 0xC3};

   pf.f.m = mas[1];
   pf.f.m += mas[2];
   pf.f.m += mas[3];
 
На выходе левое число.

Подскажите пожалуйста как мне записать в битовое поле m, ровно 23 бита из переменной 
int a = 0x48F5C3? Буду очень благодарен.
PM MAIL   Вверх
baldina
Дата 15.4.2011, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(kiLLProg @  15.4.2011,  15:23 Найти цитируемый пост)
Пробовал делать так.
код C++
1:
2:
3:
4:
5:
char mas[] = {0x40, 0x48, 0xF5, 0xC3};
   pf.f.m = mas[1];
   pf.f.m += mas[2];
   pf.f.m += mas[3];
 
На выходе левое число.

Код

   pf.f.m = (mas[1] << 16)|(mas[2] << 8)|mas[3];



Цитата(kiLLProg @  15.4.2011,  15:23 Найти цитируемый пост)
как мне записать в битовое поле m, ровно 23 бита из переменной 
int

i
Код

//младшие
pf.f.m = x & 0x7FFFFF;
//старшие
int bits = sizof(x) * 8 - 23;
pf.f.m = (x & (0x7FFFFF<<bits))>>bits;

PM MAIL   Вверх
kiLLProg
Дата 16.4.2011, 09:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 1.10.2008

Репутация: нет
Всего: нет



Цитата(baldina @  15.4.2011,  17:00 Найти цитируемый пост)
pf.f.m = (mas[1] << 16)|(mas[2] << 8)|mas[3];

Так пробовал. Не получается. 
Код

//младшие
pf.f.m = x & 0x7FFFFF; // А это зачем????
//старшие
int bits = sizof(x) * 8 - 23;  
pf.f.m = (x & (0x7FFFFF<<bits))>>bits;

Так то же не правильный результат. Но когда я экспериментировал с этим кодом. Я случайно в одной строке написал бессмысленное значение.
Код

// Программа (2)
int bits = sizeof(x) * 8 - 223; // было int bits = sizof(x) * 8 - 23;
pf.f.m = (x & (0x7FFFFF<<bits));  // убрал <<bits
 
Не посмотрев, откомпилировал код, и вуаля! Правильное значение (3.14). Почему так происходит я ХЗ, но это интересный пример для рассмотрения. Я не долго радовался.

Когда значение переменой записано вручную int a = 0x48F5C3, то в структуру можно сразу записать так pf.f.m = a. На самом деле переменная будет выглядеть так a = 0x48F5C300, после сшивания из отдельных байтов. Прошу меня извинить, я затупил чуток. Нужно было ровно 23 бита вытащить не из 0x48F5C3, а из 0x48F5C300. Т.к. в 4х байтовом int будет пустовать один байт всегда. А вот эти нули как раз не нужны. Вот я и обломался когда  в х вбил 0x48F5C300 прогнал программу (2) и получил левое значение.   

Решение проблемы оказалось простое как три бакса  smile.  48F5C300=1001000111101011100001100000000 - жирные нули - лишние. 
0048F5C3=10010001111010111000011 - Нет лишних нулей!!! Ровно 23 нужных бита   smile smile  smile
Как я раньше только не измывался над компилятором. Какие я только способы выуживания битов не перепробовал. Короче код программы.
Код

#include <stdio.h>

union ParsedFloat
{
    float v;                 // значение
        struct
    {
        unsigned int m : 23; // мантисса
        unsigned int e : 8;  // показатель степени
        unsigned int s : 1;  // знак
    } f;
};

char mas[] = {0x40, 0x48, 0xF5, 0xC3};


int main()
{
       ParsedFloat pf;

        //int x = 0x4048F5C3;
        int x = 0x4048F5C3;
        int tmp;
        unsigned char a1;
        
       // Получаем знак
        tmp = x;
        //tmp = tmp >> 31;
        //if (tmp & 1)
        if (tmp & 0x80000000) //0x80000000 = 10000000..... 
          pf.f.s = 1;
        else
          pf.f.s = 0;

        //получаем порядок
        tmp = x;
        tmp = tmp >> 23;

        a1 = tmp;
        pf.f.e = a1;

        //Получаем мантиссу
        tmp = x;
        tmp = tmp << 8;
        tmp = tmp >> 8;

        pf.f.m = tmp;

        printf("%f\n", pf.v);
        getchar();
}

Вот и всё!  smile  smile  smile
Использованные статьи:
Интернет калькулятор 
Работа с битами
Отсюда взял структуру
И многие другие.

Мне до сих пор интересно. Как из x = 0x48F5C300 вытащить только 23 бита?

Это сообщение отредактировал(а) kiLLProg - 16.4.2011, 09:41
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0801 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.