Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Свой тип переменных


Автор: gepard 18.5.2004, 09:25
Могу ли я как-нибудь завести свой тип, который, например будет оперрировать с числами с плав. точкой и будет иметь диапозон [-5;5]?
И, есесно, будет занимать объём памяти соответствующе - маленький.



Автор: chipset 18.5.2004, 09:34
пиши класс, оверлоадь оператор '=', проверяей на значение... примерно так... smile.gif

Автор: bel_nikita 18.5.2004, 09:41
Я думаю, что вот так: [-5][5] tounge.gif

Автор: maxim1000 18.5.2004, 10:31
Цитата
Могу ли я как-нибудь завести свой тип, который, например будет оперрировать с числами с плав. точкой и будет иметь диапозон [-5;5]?
И, есесно, будет занимать объём памяти соответствующе - маленький.

и почему же он будет занимать маленький объем памяти?
ограничение модуля пятеркой можно рассмотреть как ограничение на мантиссу (не больше там чего-то... около 2-3)
это - приблизительно половина диапазона, значит выиграть получится 1 бит

Автор: DenDen 18.5.2004, 13:15
Я бы скзал что, ограничение модуля 5 как раз устанавливает ограничение на сдвиг(<3).
А почему нельзя просто
1 бит -знак
3 бита--целая часть
скока надо битов дробная.
и того, если тебе надо обеспечить диапазон 10^-15
10=2^3=>диапазон=49 бит, но диапазон будет чуть хуже
или 8 байт для даже большей точность чем 10^-15

Автор: maxim1000 18.5.2004, 14:49
Цитата
А почему нельзя просто
1 бит -знак
3 бита--целая часть
скока надо битов дробная.
и того, если тебе надо обеспечить диапазон 10^-15
10=2^3=>диапазон=49 бит, но диапазон будет чуть хуже
или 8 байт для даже большей точность чем 10^-15

можно и так, но в вопросе было сказано про числа с плавающей запятой, а здесь описаны с фиксированной
кстати, я ошибся маленько:
Цитата
ограничение модуля пятеркой можно рассмотреть как ограничение на мантиссу (не больше там чего-то... около 2-3)
это - приблизительно половина диапазона, значит выиграть получится 1 бит

конечно же здесь имелась в виду экспонента

Автор: mr.DUDA 18.5.2004, 15:16
gepard, вот лови:

Цитата
#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()
    {
       
bool less0 = value>0?false:true;
       
float res = (less0?-1:1)
            *
float((less0?-value:value)&0x7fff)/4096;
       
// округляем до тысячных долей
       
res = float(int(res*1000)
            +(
less0?-1:1))/1000;
       
// ограничиваем пятью после округления
       
Limit5(res);
       
// возвращаем результат
       
return res;
    }
   
// функция устанавливает this->value равным "v"
   
void FromFloat(float v)
    {
       
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;
}


Автор: DenDen 19.5.2004, 09:34
mr.DUDA[b], апплодисменты.
Вот не такой зрелищный вариант для типов с фиксированной и плавующей точкой.

#include<iostream.h>
#include<mem.h>
#include <windows.h>

typedef struct _fix_data
{
unsigned zn:1;
unsigned ch:15;
struct _fix_data &operator=(float a);
}fd,*pfd;

typedef struct _new_float_data
{
unsigned zn:1;
unsigned exp:5;
unsigned mant:26;
struct _new_float_data &operator=(float);
}nfd,*pnfd;


fd operator+(fd,fd);
nfd operator+(nfd,nfd);


nfd& nfd::operator=(float a)
{
if((a>5)|(a<-5))
return *this;
this->zn=(a<0);
(a<0)?(a=-a)sad.gifa=a);
int i=0;
while(a<33554432)
{
a*=2;
i++;
}
this->exp=i;
this->mant=(unsigned long)(int)a;
return *this;
}





fd& fd::operator=(float a)
{
if((a>5)|(a<-5))
return *this;
char zn=(a<0);
(a<0)?(a=-a)sad.gifa=a);
a*=4096;
this->ch=(unsigned long)a;
this->zn=zn;
return *this;
}




ostream& operator<<(ostream& f,fd a)
{
double k;
k=((double)a.ch)/4096;
(a.zn>0)?(k=-k)sad.gifk=k);
f<<k;
}

ostream& operator<<(ostream& f,nfd a )
{
double k;
unsigned long t=(1<<(a.exp));
k=(double)(a.mant)/(double)t;
k*=(1-2*(a.zn>0));
f<<k;
}

fd operator+(fd a,fd b)
{
long n=a.zn+b.zn;
long n_2=0;
char fl;
if(n==0)
{
a.ch+=b.ch;
while(a.ch>20480)
a.ch-=20480;
a.zn=0;
return a;
}
else if(n==2)
{
a.ch+=b.ch;
while(a.ch>20480)
a.ch-=20480;
a.zn=1;
return a;
}
else if(n==1)
{
if(b.ch>a.ch)
{
a.ch=b.ch-a.ch;
a.zn=-a.zn;
}
else
a.ch=a.ch-b.ch;
return a;
}
}





nfd operator+(nfd a,nfd b)
{
char n =a.zn+b.zn;
unsigned long aa;
unsigned long bb;
unsigned long c;
(a.exp<b.exp)?(c=a.exp)sad.gifc=b.exp);
aa=(a.mant>>(a.exp-c));
bb=(b.mant>>(b.exp-c));
a.exp=c;
if((n==0)|(n==2))
{
aa+=bb;
if(aa>67108864)
{
aa>>1;
a.exp--;
}
if(aa>41943040)
{
aa-=41943040;
}
while(aa<0x2000000)
{
aa*=2;
a.exp++;
}
a.mant=aa;
return a;
}
if(n==1)
{
if(bb>aa)
{
aa=bb-aa;
a.zn=-a.zn;
}
else
aa=aa-bb;
while(aa<0x2000000)
{
aa*=2;
a.exp++;
}
a.mant=aa;
return a;
}


}




int main(int arc,char** arv)
{
double a;
double b;
nfd bc;
nfd ad;
bc=1.127;
ad=-4.33;
ad=ad+bc;


cout<<ad<<' '<<(4.33-1.127);
cin>>a;
int i;
i++;
}



Автор: mr.DUDA 19.5.2004, 09:39
Проблема битовых полей - это зависимость от компилятора. Неизвестно, каким по старшинству будет первое битовое поле в структуре, а каким-последнее.

Автор: DenDen 19.5.2004, 09:49
извини, за дискуссию..
Ты, безусловно, прав, однако тут с полями общаются по отдельности(т.е через компилятор).
Вообще если бы не инвертированная мантисса в флоте и дубле, это следовало бы писать все на асме(было бы заметно быстрее)(видимо, это и задумывалось как курсовик по асму), но с учетом особенности 1--ломает.
//З.ы. Что тебе в скобках то не понравилось???
Хм, ну я и урод... Люди скажите, как коды вставлять по нормальному, а то
вместо скобок смайлы лезут

Автор: gepard 19.5.2004, 12:03
Спасибо, всем. Я ещё такой глупый. thumbs-up.gif

Автор: Sined 19.5.2004, 20:05
Это ты к чему???

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)