Форум программистов, компьютерный форум CyberForum.ru

Побитовое копирование double - C++

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 26, средняя оценка - 5.00
insideone
Модератор
Автор FAQ
 Аватар для insideone
3630 / 908 / 48
Регистрация: 10.01.2010
Сообщений: 2,446
10.01.2010, 02:32     Побитовое копирование double #1
Доброго времени суток!
Преамбула: В целях интеграции Lua в движок C++ пытаюсь написать класс который может помещать в себя все типы данных в определенном порядке, чтобы можно было передать ссылку на этот класс в функцию которая отправит эти данные в обработчик Lua. Класс почти написал за исключением поддержи double - потому что для double нельзя использовать побитовые операции, через которые лаконично преобразуются остальные типы.
Собственно вопрос: как считать побитово double?
Файлы с кодом прилагаются....
Вложения
Тип файла: zip Stack.zip (2.7 Кб, 19 просмотров)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
10.01.2010, 02:57     Побитовое копирование double #2
не очень понимаю что за побитовые операции, разместить в определенном порядке, чем memset не подойдет, обращатся можно к отдельным байтам путем приведения к (char*)?
вообщем, что значит побитово считать?
Nick Alte
Эксперт С++
1594 / 986 / 117
Регистрация: 27.09.2009
Сообщений: 1,902
Завершенные тесты: 1
10.01.2010, 12:03     Побитовое копирование double #3
Я тоже писал интеграцию Lua в С++. Много интересного нарисовал. Но доделать не успел, когда припекло. Надо было встроить набор дополнительных функций. И ничего, на чистом Lua API отлично всё написалось, быстро и без ошибок.
Что же касается битовых операций, то можно воспользоваться union:
C++
1
2
3
4
5
6
union BitDouble {
    double dbl;
//    __int64 bits64;                      // Ненужные члены можно просто закомментировать
    unsigned long bits32[2];
    unsigned char bits8[8];
};
insideone
Модератор
Автор FAQ
 Аватар для insideone
3630 / 908 / 48
Регистрация: 10.01.2010
Сообщений: 2,446
10.01.2010, 16:15  [ТС]     Побитовое копирование double #4
Цитата Сообщение от alex_x_x Посмотреть сообщение
не очень понимаю что за побитовые операции, разместить в определенном порядке, чем memset не подойдет, обращатся можно к отдельным байтам путем приведения к (char*)?
вообщем, что значит побитово считать?
Ну... задумываясь как можно было бы хранить различные данные я подумал о том что bool, char, и все int это простые числа над которыми можно производить побитовую операцию & 1
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <class AnyType>
void WriteToDB(AnyType Var){
   unsigned char size = sizeof(Var)*8; получаем размер в БИТах
   unsigned char LastPos = GetCursor(); // последняя позиция в БД
   for (unsigned char CurPos = LastPos; CurPos < (LastPos + size); CurPos++)
   {
       this->DB[CurPos] = Var & 1; // отрываем последний БИТ от Var и записываем его в БД
       Var = Var >> 1; // делаем предпоследний БИТ последним БИТом =)
   }
   SetLink(LastPos, size); // устанавливаем метку где записались данные
}
// Результат работы WriteToDB((unsigned short int)3)
// исходные данные 3 = 0000 0000 0000 0011
// this->DB = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
// PS. БД bool массив[/B]
а вот double не разрешает над собой творить такого, хотя это глупо все же состоит из битов так или иначе

Добавлено через 1 час 27 минут
Цитата Сообщение от Nick Alte Посмотреть сообщение
Что же касается битовых операций, то можно воспользоваться union:
C++
1
2
3
4
5
6
union BitDouble {
    double dbl;
//    __int64 bits64;                      // Ненужные члены можно просто закомментировать
    unsigned long bits32[2];
    unsigned char bits8[8];
};
union хорош конечно... но тут не сделаешь автоматического выбора куда ему писать. вот если бы можно было
C++
1
BitDouble = 3;
... хотя то что сейчас там тоже все за счет кучи перегрузок делается. Хм... ну ещё минус то что union занимает максимум пространства из возможного
Nick Alte
Эксперт С++
1594 / 986 / 117
Регистрация: 27.09.2009
Сообщений: 1,902
Завершенные тесты: 1
10.01.2010, 16:18     Побитовое копирование double #5
Какой ещё максимум? Такой union займёт ровно столько же места, сколько занимает double. Ну а что до автовыбора, кучи перегрузок не понадобится. Достаточно сделать простейший класс и определить ему operator = (double);
insideone
Модератор
Автор FAQ
 Аватар для insideone
3630 / 908 / 48
Регистрация: 10.01.2010
Сообщений: 2,446
10.01.2010, 17:15  [ТС]     Побитовое копирование double #6
Цитата Сообщение от Nick Alte Посмотреть сообщение
Какой ещё максимум? Такой union займёт ровно столько же места, сколько занимает double. Ну а что до автовыбора, кучи перегрузок не понадобится. Достаточно сделать простейший класс и определить ему operator = (double);
Я имею ввиду что не хочу для double вводить отдельные какие то переменные\структуры. Необходимо создать систему которой все равно какие данные в неё вводятся.
C++
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class USTACK{
public:
    struct DATA{
        union A{
            int i;
            char c;
            double d;
            float f;
            bool b;
        } Data;
        unsigned char Type;
        
    } DB[USTACK_SIZE];
 
    unsigned char count;
 
    USTACK::USTACK();
 
    USTACK& operator<<(int var);
    USTACK& operator>>(int& var);
};
 
USTACK& USTACK::operator<<(int var){
    this->DB[this->count].Data.i = var;
    this->count++;
return (*this);
}
 
USTACK& USTACK::operator>>(int& var){
    unsigned char LastID = this->count-1;
    var = this->DB[LastID].Data.i;
    this->DB[LastID].Data.i = NULL;
    this->count--;
return (*this);
}
 
int main()
{
    // Переменные для тестирования работы
    bool bX = true, bY = false, bZ = true;
    char cX[100] = {NULL}, cY[100] = {NULL}; unsigned char cZ[100] = {NULL};
    int iX = 3; short int iY = 200; long long int iZ = 55;
 
    USTACK In;
    In << 4 << 6;
    In >> iX >> iY;
}
Т.е. я могу лишь искуственно выбирать куда мне ложить данные. Если переписать оператор = то для него нужно будет писать тоже входные данные, а они могут быть разными, т.е. все равно ручками. Может я чего то непонимаю, приведите пожалуйста код который демонстрирует функционал который вы имеете ввиду.
zim22
depict1
 Аватар для zim22
276 / 141 / 2
Регистрация: 11.07.2009
Сообщений: 606
10.01.2010, 17:31     Побитовое копирование double #7
почему бы не преобразовать любой поступивший тип в массив char той длины, которая будет возвращена оператором sizeof? и уже для char потом применять битовые операции.
insideone
Модератор
Автор FAQ
 Аватар для insideone
3630 / 908 / 48
Регистрация: 10.01.2010
Сообщений: 2,446
10.01.2010, 17:42  [ТС]     Побитовое копирование double #8
Цитата Сообщение от zim22 Посмотреть сообщение
почему бы не преобразовать любой поступивший тип в массив char той длины, которая будет возвращена оператором sizeof? и уже для char потом применять битовые операции.
Хм, очень интересно. В результате в каждом элементе массива будут хранится определенные байты входных данных? А как это сделать? И как лучше хранить остаток от double?
Nick Alte
Эксперт С++
1594 / 986 / 117
Регистрация: 27.09.2009
Сообщений: 1,902
Завершенные тесты: 1
10.01.2010, 17:43     Побитовое копирование double #9
Я-то предпочитаю вообще избегать таких конструкций. Смешение разнородных данных в одном и том же месте - не самый выигрышный ход. К динамической типизации и типам наподобие Variant надо прибегать лишь тогда, когда более подходящие варианты недоступны.
zim22
depict1
 Аватар для zim22
276 / 141 / 2
Регистрация: 11.07.2009
Сообщений: 606
10.01.2010, 17:55     Побитовое копирование double #10
Цитата Сообщение от insideone Посмотреть сообщение
В результате в каждом элементе массива будут хранится определенные байты входных данных?
наверно. я не знаю, как вещественный числа представлены в памяти ПК.

Цитата Сообщение от insideone Посмотреть сообщение
А как это сделать?
C++
1
2
3
4
5
6
7
double z = 33.228844649;
const int zSize = sizeof(z);
char zArray[zSize] = {0};
memcpy(zArray, &z, zSize);
 
double convertedZ = 0;
memcpy(&convertedZ, zArray, zSize);
Цитата Сообщение от insideone Посмотреть сообщение
И как лучше хранить остаток от double?
какой остаток?
insideone
Модератор
Автор FAQ
 Аватар для insideone
3630 / 908 / 48
Регистрация: 10.01.2010
Сообщений: 2,446
10.01.2010, 19:04  [ТС]     Побитовое копирование double #11
zim22: Большое спасибо за код, все таки я ещё плоховато знаю стандартные функции библиотек С++. Получается можно отлично приводить любой тип данных к char массиву, значит класс который сейчас есть будет использовать char DB[] а не bool DB[] и все будет ОК) небольшая потеря для bool типа думаю не особо страшна) Про остаток не актуально это я уже подумывал как бы извратиться хранить double отдельно целую и дробную части)

Nick Alte: Ну да Variant это конечно плохо, память используется неоптимально и все такое, но я делаю класс который является массивом информации (любой) а не единцей информации. И при этом для хранения элемента класса требуется столько байт сколько он весит. Накладные расходы - байт с информацией о местонахождении элемента в массиве класса.
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16941 / 5346 / 328
Регистрация: 30.03.2009
Сообщений: 14,372
Записей в блоге: 26
10.01.2010, 19:23     Побитовое копирование double #12
Цитата Сообщение от Nick Alte Посмотреть сообщение
Я-то предпочитаю вообще избегать таких конструкций. Смешение разнородных данных в одном и том же месте - не самый выигрышный ход. К динамической типизации и типам наподобие Variant надо прибегать лишь тогда, когда более подходящие варианты недоступны.
В случае с Lua такие варианты неприемлимы, т.к. нужно транзитом передать данные через код, который "ничего не знает" ни про какие типы

Цитата Сообщение от insideone Посмотреть сообщение
Ну да Variant это конечно плохо, память используется неоптимально и все такое, но я делаю класс который является массивом информации (любой) а не единцей информации. И при этом для хранения элемента класса требуется столько байт сколько он весит. Накладные расходы - байт с информацией о местонахождении элемента в массиве класса.
Боязнь потерять 10 байт (30 байт, 100 байт) на фоне нескольких десятков или сотен килобайт (а то и больше), отжираемых интерпретатором Lua - как-то смешно выглядит. Экономить память хорошо, но в разумных пределах.

А что по постановке задачи - я так и не понял, в чём конкретно состоит проблема
Nick Alte
Эксперт С++
1594 / 986 / 117
Регистрация: 27.09.2009
Сообщений: 1,902
Завершенные тесты: 1
10.01.2010, 19:29     Побитовое копирование double #13
Variant плох не потерями памяти, а безопасностью типов и нежелательными побочными эффектами. Насчёт его необходимости в случае с Lua мне можно не рассказывать, я преспокойно обхожусь без таких вещей. Функции Lua API о типах превосходно осведомлены.
insideone, а так ли уж и нужен такой класс? Какой в нём прок? Какие есть причины, по которым без него нельзя обойтись?
insideone
Модератор
Автор FAQ
 Аватар для insideone
3630 / 908 / 48
Регистрация: 10.01.2010
Сообщений: 2,446
10.01.2010, 20:16  [ТС]     Побитовое копирование double #14
Хочется как то обеспечить себе удобство написав высокоуровневые функции. Конечно для кого то я извращаюсь, но мне нравится экспериментировать. С++ сложен и осваивается не быстро, тем более я учусь для себя, а так я студент даже не IT специальности. С интеграцией Lua знаком со вчера так что...
Я писал функцию Call вызывающую Lua функцию, там нужно передать через push параметры, при этом они могут быть разных типов и для этого используются разные функции lua API. Были написаны следующие перегрузки
C++
1
2
3
4
    void Push(const bool& arg);
    void Push(const double& arg);
    void Push(const int& arg);
// etc
Хотелось бы реализовать Call так...
C++
1
STACK& Call(char* FuncName, STACK* InData);
вызов
C++
1
StackVar = Call("TestFunc", StackVar << 2 << 4 << 5);
... В смысле через написаный стек класс мы передаем параметры и обратно принимаем через него же.

В принципе можно обойтись без всего этого но наверное будет не так красиво =)
Nick Alte
Эксперт С++
1594 / 986 / 117
Регистрация: 27.09.2009
Сообщений: 1,902
Завершенные тесты: 1
10.01.2010, 20:55     Побитовое копирование double #15
Ну да, всегда приходится чем-то жертвовать. Я по этому поводу пытаюсь исхитрить так, чтобы операторы << сразу помещали значения на стек Lua, без посредников.
Впрочем, после того, как я обнаружил, что и на чистом Lua API мои задачи решились быстро, гладко и без проблем, стремление допилить сей binding несколько поутихло. Может, когда-нибудь соберусь и доделаю...
insideone
Модератор
Автор FAQ
 Аватар для insideone
3630 / 908 / 48
Регистрация: 10.01.2010
Сообщений: 2,446
10.01.2010, 21:13  [ТС]     Побитовое копирование double #16
Хм... а можно сделать так?
C++
1
2
3
4
5
LUA Lua; // мой класс реализующий прослойку между С++ и Lua
// Передаем в стек луа "TestFunc", 3, 5, потом выполняя = посылаем команду об отправки стека
// с вызовом функции, а результат возвращаем в виде класса стека который принимает любые типы данные и отдает любые типы данных.
STACK& Result = Lua << "TestFunc" << 3 << 5 = LUA_CALL;
int x = Result[0];
Вот тут как раз и будут сразу посылаться в стек луа без посредников... а вот как лучше вернуть результат, может можно сделать проще?

Не по теме:

Воистину C++ безграничен для извращенств и создания самого неочевидного кода



Не по теме:

Собственно у меня вообще возникают сомнения в необходимости возвращать из Lua множество значений однако как знать...

Nick Alte
Эксперт С++
1594 / 986 / 117
Регистрация: 27.09.2009
Сообщений: 1,902
Завершенные тесты: 1
10.01.2010, 21:22     Побитовое копирование double #17
Насчёт возврата дело хитрое. Вернуть-то может и несколько значений. У меня там под это дело написана специальная прослойка, которая распихивает полученные значения куда надо.
insideone
Модератор
Автор FAQ
 Аватар для insideone
3630 / 908 / 48
Регистрация: 10.01.2010
Сообщений: 2,446
10.01.2010, 21:37  [ТС]     Побитовое копирование double #18
Сделал простую перегрузку
C++
1
2
3
4
5
template <class AnyData>
LUA& LUA::operator << (AnyData Data){
    Push(Data);
return (*this);
}
Push'ы просты:
C++
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
26
27
void LUA::Push(const bool& arg){
    lua_pushboolean(pL, arg ? 1 : 0);
}
void LUA::Push(const double& arg){
    lua_pushnumber(pL, arg);
}
void LUA::Push(const int& arg){
    lua_pushnumber(pL, arg);
}
void LUA::Push(char& arg){
    lua_pushstring(pL, &arg);
}
void LUA::Push(const char& arg){
    lua_pushstring(pL, &arg);
}
void LUA::Push(const char& arg, int len){
    lua_pushlstring(pL, &arg, len);
}
void LUA::Push(const std::string& arg){
    lua_pushstring(pL, arg.c_str());
}
void LUA::Push(const std::string& arg, int len){
    lua_pushlstring(pL, arg.c_str(), len);
}
void LUA::Push(lua_CFunction CFunc){
    lua_pushcfunction(pL, CFunc);
}
Выполняю:
C++
1
Lua << "talk" << 2 << 4;
Прохожу дебаггером... и первым делом куда переходит указатель дебага является перегрузка void LUA::Push(const bool& arg) с аргументом true... интересно так безпалевно конвертировать char* в bool ( чтобы это значило?
Nick Alte
Эксперт С++
1594 / 986 / 117
Регистрация: 27.09.2009
Сообщений: 1,902
Завершенные тесты: 1
10.01.2010, 23:05     Побитовое копирование double #19
У меня похоже сделано, но типы только те, что соответствуют луашным. Ну а преобразование указателя в bool - штука элементарная, хотя и печальная. false для нулевого указателя, true для ненулевого.
Разумеется, надо было вместо char'ов всяких сделать оверлоад для const char*
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.01.2010, 00:08     Побитовое копирование double
Еще ссылки по теме:

Работа с dlsym. Invalid conversion from 'void *' to 'double(*)(double)' C++ Linux
Побитовое замещение C++
C++ Builder Too few parametrs in call to '_fastcall LogN(cont log double, const long double)'
Побитовое сравнение C++
C++ Побитовое представление числа

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
insideone
Модератор
Автор FAQ
 Аватар для insideone
3630 / 908 / 48
Регистрация: 10.01.2010
Сообщений: 2,446
11.01.2010, 00:08  [ТС]     Побитовое копирование double #20
Цитата Сообщение от Nick Alte Посмотреть сообщение
У меня похоже сделано, но типы только те, что соответствуют луашным. Ну а преобразование указателя в bool - штука элементарная, хотя и печальная. false для нулевого указателя, true для ненулевого.
Разумеется, надо было вместо char'ов всяких сделать оверлоад для const char*
Хм.. да, действительно char* дало результат. Просто делал по примеру, там все было с type&... а я в этом ещё немного запутываюсь. Пожалуй char& это наверное работа по ссылке с 1 символом)

Собственно тема решена) Спасибо всем кто отвечал, то что получилось выкладываю...
А вот как пользоваться:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main()
{
    STACK S;
    S << 'b' << true << 342.2342 << "12345" << 'a' << "678";
    char x = NULL;
    S.GetData(x, 4);
    bool y = false;
    long double z = 0.34254424342;
    char* cX = NULL;
    char cY = NULL;
    char* cZ = NULL;
    S >> cX >> cY >> cZ >> z >> y >> x;
return 0;
}
Хотел ещё прикрутить чтобы класс понимал что он хранит в каждой ячейки да голова уже тяжелая, потом может.
Вложения
Тип файла: zip Stack.zip (1.0 Кб, 9 просмотров)
Yandex
Объявления
11.01.2010, 00:08     Побитовое копирование double
Ответ Создать тему
Опции темы

Текущее время: 18:05. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru