Полезное для программистов:

Фриланс
Новости
Статьи
   
Рубрики:


Как создать свой тип переменных

Поиск:
Для создания своего собственного, непохожего на другие, типа данных, достаточно всего лишь написать класс, хранящий (инкапсулирующий) эти данные в выбранном формате, и предоставляющий доступ к данным в одном или нескольких стандартных форматах - int, float, double и т.п., для того чтобы можно было преобразовывать данные из стандартных форматов в свой и обратно простыми операциями (присваивание, +, -, += и т.п.)

Рассмотрим процесс создания собственного типа данных на примере типа, хранящего числа диапазона [-5;5] в формате с фиксированной запятой. Примем достаточную степень точности числа равной трём знакам после запятой, что в переводе в двоичную форму составит 12 бит. На целую часть будет достаточно 3-х битов (т.к. максимум и минимум из диапазона -5...5 занимают по 3 бита), на знак числа отводится 1 бит. В сумме получается 16 бит - то есть, для внутреннего хранения данных достаточно двух байт, это тип данных short.

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

В результате получим новый тип данных, описанный классом N5 (пример работы с новым типом данных приведён в самом низу, в функции main):
Цитата
#include <stdio.h>
#include <math.h>

///////////////////////////////////////////////
// новый тип данных - число с фиксированной
// запятой в интервале от -5 по 5

class N5
{

private:
   
///////////////////////////////////////////////
    // личные данные

    // значение числа в бинарном виде:
    // 1 бит - знак
    // 3 бита - целая часть
    // 12 бит - дробная часть (до тысячных долей)
   
short value;   


protected:
   
///////////////////////////////////////////////
    // защищённые методы для работы с личными данными

    // ограничение значения "v" пятью
   
void Limit5(float &v)
    {
       
if(fabs(v)>5) v = (v>0?1:-1)*float(5);
    }

   
// преобразование this->value в тип float
   
float ToFloat()
    {
       
// Смысл следующих действий:
        // 1) получить знак в виде множителя sign (-1 или 1)
        // 2) получить значение, взяв абсолютное значение
        //    числа, преобразовать его в тип float, и
        //    разделить на 2^12, (для чисел в формате float
        //    нельзя использовать оператор >>).
        //    Таким образом, при исходном значении равном
        //    0x1234, получим знак=1, и float-значение, равное
        //    = float(0x1234)/4096
        //    = float(0 001 001000110100)>>12
        //    = float(001,001000110100) = 1,138
        // 3) умножить значение на знак числа (1 или -1)
        // 3) округлить число до тысячных долей (с корректировкой
        //    на плюс-минус одну тысячную, в зависимости от знака)
        // 4) ограничить значение результата 5-ю (Limit5)
       
float sign = float(value>0?1:-1);
       
float res = sign * float(abs(value))/4096;
       
// округляем float-значение до тысячных долей
       
res = float(int(res*1000)+sign)/1000;
       
// ограничиваем пятью после округления
       
Limit5(res);
       
// возвращаем результат
       
return res;
    }

   
// присвоение this->value значения "v"
   
void FromFloat(float v)
    {
       
// 1) ограничиваем значение "v" 5-ю
        // 2) получаем знак-множитель в виде маски (0 или 0x8000)
        // 3) умножаем исходное дробное float-значение на 2^12,
        //    затем преобразуем результат в short
        // 4) объединяем знак и short-результат операцией |
       
Limit5(v);
       
value = short(v>0?0:0x8000)|((short)(v*4096));
    }

public:

   
///////////////////////////////////////////////
    // конструкторы

    // конструктор копирования из типа T, совместимого с float
   
template<typename T> N5(T val) {*this = val;}
   
// конструктор по умолчанию (обнуление)
   
N5(): value(0) {}


   
///////////////////////////////////////////////
    // операторы

   
    // явное преобразование к типу float
   
operator float() {return ToFloat();}
   
   
// явное преобразование из типа T, совместимого с float
   
template<typename T> N5 &operator= (T val)
    {
       
FromFloat((float)val);
       
return *this;
    }
   
   
// префиксная форма ++
   
N5 &operator++()
    {*
this = ToFloat()+1; return *this;}
   
   
// постфиксная форма ++
   
N5 &operator++(int)
    {*
this = ToFloat()+1; return *this;}
   
   
// префиксная форма --
   
N5 &operator--()
    {*
this = ToFloat()-1; return *this;}
   
   
// постфиксная форма --
   
N5 &operator--(int)
    {*
this = ToFloat()-1; return *this;}
   
   
// оператор +=
   
template<typename T>
   
N5 &operator+=(T &v)
    {*
this = ToFloat()+(float)v; return *this;}

   
// оператор -=
   
template<typename T>
   
N5 &operator-=(T v)
    {*
this = ToFloat()-(float)v; return *this;}

   
// оператор *=
   
template<typename T>
   
N5 &operator*=(T v)
    {*
this = ToFloat()*(float)v; return *this;}

   
// оператор /=
   
template<typename T>
   
N5 &operator/=(T v)
    {*
this = ToFloat()/(float)v; return *this;}
};



//////////////////////////////////////////////////////
// тестовая функция для проверки работоспособности
// нового типа данных

int main(int argc, char* argv[])
{
   
N5 n = -4.567;
   
n ++;
   
n += 1;
   
n = n/2;
   
n *= 2;
   
n += 0.123;
   
n--;
   
n++;
   
n -= 2;
   
n /= (n+1);
   
printf("Result: %f\n", (float)n);
   
return 0;
}
Автор: mr.DUDA
Сайт: http://






Просмотров: 3136

 

 

Новые статьи:


Популярные:
  1. Как сделать цикличным проигрывание MIDI-файла?
  2. Создание AVI файла из рисунков
  3. Как устройство "отключить в данной конфигурации"?
  4. Kто в данный момент присоединен через Сеть?
  5. Как узнать количество доступной памяти?
  6. Как реализовать в RichEdit разноцветный текст?
  7. Как скрыть свое приложение от ProcessViewer
  8. Как программно нажать/скрыть/показ кнопку "Start"?
  9. Модуль работы с ресурсами в PE файлах
10. Функции вызова диалоговых окон выбора
11. Проверка граматики средствами Word'а из Delphi.
12. Модуль для упрощенного вызова сообщений
13. Функции для записи и чтение своих данных в, ЕХЕ- файле
14. Рекурсивный просмотр директорий
15. Network Traffic Monitor
16. Разные модули
17. Универсальная функция для обращения к любым экспортируем функциям DLL
18. Библиотека от VladS
19. Протектор для UPX'а
20. Еще об ICQ, сообщения по контакт листу?
21. Использование открытых интерфейсов
22. Теория и практика использования RTTI
23. Работа с TApplication
24. Примеры использования Drag and Drop для различных визуальных компонентов
25. Что такое порт? Правила для работы с портами
26. Симфония на клавиатуре
27. Загрузка DLL
28. Исправление автоинкремента
29. Взаимодействие с чужими окнами
30. Проверить дубляжи в столбце


 

 

 
 
На главную