Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.80/25: Рейтинг темы: голосов - 25, средняя оценка - 4.80
Автор FAQ
3684 / 961 / 114
Регистрация: 10.01.2010
Сообщений: 2,550
1

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

10.01.2010, 02:32. Показов 5221. Ответов 19
Метки нет (Все метки)

Доброго времени суток!
Преамбула: В целях интеграции Lua в движок C++ пытаюсь написать класс который может помещать в себя все типы данных в определенном порядке, чтобы можно было передать ссылку на этот класс в функцию которая отправит эти данные в обработчик Lua. Класс почти написал за исключением поддержи double - потому что для double нельзя использовать побитовые операции, через которые лаконично преобразуются остальные типы.
Собственно вопрос: как считать побитово double?
Файлы с кодом прилагаются....
0
Вложения
Тип файла: zip Stack.zip (2.7 Кб, 20 просмотров)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.01.2010, 02:32
Ответы с готовыми решениями:

Побитовое копирование рисунка
Есть задание на курсач: Разработать программу, демонстрирующую влияние установленного ...

Работа с пикселями, побитовое копирование
**Задание: Написать программу, осуществляющую побитовое копирование из одного изображения в другое....

Полное (побитовое) копирование объекта одной строчкой кода. не ссылки
Добрый день, подскажите пожалуйста, как быстро и безболезненно можно скопировать значения одного...

Ошибки error C2296: -: недопустимо, левый операнд имеет тип "double (__cdecl *)(double,double,double
Думаю из-за polp #include<iostream> #include<cmath> #include<cstdlib> using namespace std;...

19
бжни
2473 / 1682 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
10.01.2010, 02:57 2
не очень понимаю что за побитовые операции, разместить в определенном порядке, чем memset не подойдет, обращатся можно к отдельным байтам путем приведения к (char*)?
вообщем, что значит побитово считать?
0
Эксперт С++
1666 / 1038 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
10.01.2010, 12:03 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];
};
0
Автор FAQ
3684 / 961 / 114
Регистрация: 10.01.2010
Сообщений: 2,550
10.01.2010, 16:15  [ТС] 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 занимает максимум пространства из возможного
0
Эксперт С++
1666 / 1038 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
10.01.2010, 16:18 5
Какой ещё максимум? Такой union займёт ровно столько же места, сколько занимает double. Ну а что до автовыбора, кучи перегрузок не понадобится. Достаточно сделать простейший класс и определить ему operator = (double);
0
Автор FAQ
3684 / 961 / 114
Регистрация: 10.01.2010
Сообщений: 2,550
10.01.2010, 17:15  [ТС] 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;
}
Т.е. я могу лишь искуственно выбирать куда мне ложить данные. Если переписать оператор = то для него нужно будет писать тоже входные данные, а они могут быть разными, т.е. все равно ручками. Может я чего то непонимаю, приведите пожалуйста код который демонстрирует функционал который вы имеете ввиду.
0
depict1
281 / 146 / 4
Регистрация: 11.07.2009
Сообщений: 606
10.01.2010, 17:31 7
почему бы не преобразовать любой поступивший тип в массив char той длины, которая будет возвращена оператором sizeof? и уже для char потом применять битовые операции.
0
Автор FAQ
3684 / 961 / 114
Регистрация: 10.01.2010
Сообщений: 2,550
10.01.2010, 17:42  [ТС] 8
Цитата Сообщение от zim22 Посмотреть сообщение
почему бы не преобразовать любой поступивший тип в массив char той длины, которая будет возвращена оператором sizeof? и уже для char потом применять битовые операции.
Хм, очень интересно. В результате в каждом элементе массива будут хранится определенные байты входных данных? А как это сделать? И как лучше хранить остаток от double?
0
Эксперт С++
1666 / 1038 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
10.01.2010, 17:43 9
Я-то предпочитаю вообще избегать таких конструкций. Смешение разнородных данных в одном и том же месте - не самый выигрышный ход. К динамической типизации и типам наподобие Variant надо прибегать лишь тогда, когда более подходящие варианты недоступны.
0
depict1
281 / 146 / 4
Регистрация: 11.07.2009
Сообщений: 606
10.01.2010, 17:55 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?
какой остаток?
1
Автор FAQ
3684 / 961 / 114
Регистрация: 10.01.2010
Сообщений: 2,550
10.01.2010, 19:04  [ТС] 11
zim22: Большое спасибо за код, все таки я ещё плоховато знаю стандартные функции библиотек С++. Получается можно отлично приводить любой тип данных к char массиву, значит класс который сейчас есть будет использовать char DB[] а не bool DB[] и все будет ОК) небольшая потеря для bool типа думаю не особо страшна) Про остаток не актуально это я уже подумывал как бы извратиться хранить double отдельно целую и дробную части)

Nick Alte: Ну да Variant это конечно плохо, память используется неоптимально и все такое, но я делаю класс который является массивом информации (любой) а не единцей информации. И при этом для хранения элемента класса требуется столько байт сколько он весит. Накладные расходы - байт с информацией о местонахождении элемента в массиве класса.
0
Evg
Эксперт CАвтор FAQ
21191 / 8208 / 632
Регистрация: 30.03.2009
Сообщений: 22,518
Записей в блоге: 30
10.01.2010, 19:23 12
Цитата Сообщение от Nick Alte Посмотреть сообщение
Я-то предпочитаю вообще избегать таких конструкций. Смешение разнородных данных в одном и том же месте - не самый выигрышный ход. К динамической типизации и типам наподобие Variant надо прибегать лишь тогда, когда более подходящие варианты недоступны.
В случае с Lua такие варианты неприемлимы, т.к. нужно транзитом передать данные через код, который "ничего не знает" ни про какие типы

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

А что по постановке задачи - я так и не понял, в чём конкретно состоит проблема
0
Эксперт С++
1666 / 1038 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
10.01.2010, 19:29 13
Variant плох не потерями памяти, а безопасностью типов и нежелательными побочными эффектами. Насчёт его необходимости в случае с Lua мне можно не рассказывать, я преспокойно обхожусь без таких вещей. Функции Lua API о типах превосходно осведомлены.
insideone, а так ли уж и нужен такой класс? Какой в нём прок? Какие есть причины, по которым без него нельзя обойтись?
0
Автор FAQ
3684 / 961 / 114
Регистрация: 10.01.2010
Сообщений: 2,550
10.01.2010, 20:16  [ТС] 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);
... В смысле через написаный стек класс мы передаем параметры и обратно принимаем через него же.

В принципе можно обойтись без всего этого но наверное будет не так красиво =)
0
Эксперт С++
1666 / 1038 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
10.01.2010, 20:55 15
Ну да, всегда приходится чем-то жертвовать. Я по этому поводу пытаюсь исхитрить так, чтобы операторы << сразу помещали значения на стек Lua, без посредников.
Впрочем, после того, как я обнаружил, что и на чистом Lua API мои задачи решились быстро, гладко и без проблем, стремление допилить сей binding несколько поутихло. Может, когда-нибудь соберусь и доделаю...
0
Автор FAQ
3684 / 961 / 114
Регистрация: 10.01.2010
Сообщений: 2,550
10.01.2010, 21:13  [ТС] 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 множество значений однако как знать...

0
Эксперт С++
1666 / 1038 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
10.01.2010, 21:22 17
Насчёт возврата дело хитрое. Вернуть-то может и несколько значений. У меня там под это дело написана специальная прослойка, которая распихивает полученные значения куда надо.
0
Автор FAQ
3684 / 961 / 114
Регистрация: 10.01.2010
Сообщений: 2,550
10.01.2010, 21:37  [ТС] 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 ( чтобы это значило?
0
Эксперт С++
1666 / 1038 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
10.01.2010, 23:05 19
У меня похоже сделано, но типы только те, что соответствуют луашным. Ну а преобразование указателя в bool - штука элементарная, хотя и печальная. false для нулевого указателя, true для ненулевого.
Разумеется, надо было вместо char'ов всяких сделать оверлоад для const char*
0
Автор FAQ
3684 / 961 / 114
Регистрация: 10.01.2010
Сообщений: 2,550
11.01.2010, 00:08  [ТС] 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;
}
Хотел ещё прикрутить чтобы класс понимал что он хранит в каждой ячейки да голова уже тяжелая, потом может.
0
Вложения
Тип файла: zip Stack.zip (1.0 Кб, 11 просмотров)
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
11.01.2010, 00:08

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Ошибка: error LNK2001: unresolved external symbol "double __cdecl Akk(double,double,double)"
#include &lt;iostream&gt; #include &lt;cmath&gt; using namespace std; double Akk(double x, double y, double...

Ругается на строчку double[] wArray = new double[n];, double[] w = new double[n];
Ругается на строчку double wArray = new double;, double w = new double; Не удаётся преобразовать...

Почему мы пишем double x (double y)? а не через запятую double x,y
почему мы пишем double x (double y)? а не через запятую double x,y

Написать функцию int Search ( double A[], int n , double x), которая находит в массиве double A[n] элемент, значение которого равно x
Написать функцию int Search ( double A, int n , double x), которая находит в массиве double A...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.