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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Использование double вместо float, повысится ли точность вычислений? 
:(
    Опции темы
Нитонисе
Дата 30.8.2012, 15:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(math64 @  30.8.2012,  14:29 Найти цитируемый пост)
Только при хранении чисел в виде дробей это чаще всего будет не оправдано.

Потому что какие бы не были длинные числа в числителе и знаменателе - все равно будут переполняться?
PM MAIL   Вверх
Нитонисе
Дата 30.8.2012, 15:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Если я буду иметь возможность хранить числа в дробях, где числитель и знаменатель могут быть представлены числами из 300 (что соответсвует максимальной емкости типа double) или дальше больше знаков, неужели этого не хватит для практических вычислений? Конечно, в определенный момент может наступить переполнение, но ведь оно может наступить и при работе с double. При этом работая с double точность теряется, чем больше вычислений мы производим, а при работе с дробями не теряется вообще.
PM MAIL   Вверх
Alexeis
Дата 30.8.2012, 15:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

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



Цитата(Нитонисе @  30.8.2012,  16:19 Найти цитируемый пост)
где числитель и знаменатель могут быть представлены числами из 300 (что соответсвует максимальной емкости типа double) или дальше больше знаков, неужели этого не хватит для практических вычислений?

   Какие еще 300 ? У дабла 15-16 цифр. Если нужно максимальное число цифр, то тут я думаю поможет __int64 . У него 19 значащих цифр.  По размеру он как double, только не хранит в себе показатель степени и вообще сам по себе число целое.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Нитонисе
Дата 30.8.2012, 16:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Alexeis @  30.8.2012,  15:32 Найти цитируемый пост)
 Какие еще 300 ? У дабла 15-16 цифр.

Я не про точность, а про емкость. Тип double может иметь максимальное значение состоящее из порядка трехсот знаков. При этом точность будет, как вы говорите, в 15-16-ти. А что если int будет иметь возможность хранить такие же большие числа? Он все равно не будет годиться для дробного представления чисел?

Я тут набросал класс super_int, который может хранить числа примерно такой же размерности как и double. Вот если ими представить дробь, неужели в практических вычислениях все равно будет переполняться этот тип?

Код

#include <vcl.h>

class super_int
{
    public:
        super_int();
        super_int(int v);
        super_int operator+(super_int n2);
        UnicodeString to_string();

    private:
        int involve(int n, int d);

    private:
        short int value[100];
        short int rang;
};

super_int::super_int()
{
    value[0] = 0;
    rang = 1;
}

super_int::super_int(int v)
{
    if (v >= 1000000000)
        rang = 4;
    else if (v >= 1000000)
        rang = 3;
    else if (v >= 1000)
        rang = 2;
    else
        rang = 1;
    for (short int i=0; i<rang; i++)
    {
        if (i != rang-1)
            value[i] = (v - involve(1000,i+1)*(v/involve(1000,i+1)))/involve(1000,i);
        else
            value[i] = v/involve(1000,i);
    }
}

super_int super_int::operator+(super_int n2)
{
    short int rang_max;
    if (rang > n2.rang)
        rang_max = rang;
    else
        rang_max = n2.rang;
    super_int n;
    n.rang = rang_max;
    for (short int i=0; i<rang_max; i++)
    {
        n.value[i] = n.value[i] + value[i] + n2.value[i];
        if (n.value[i] > 999)
        {
            n.value[i+1] = n.value[i] - 999;
            n.value[i] = 999;
            if (i == rang_max-1)
                n.rang++;
        }
        else n.value[i+1] = 0;
    }
    return n;
}

int super_int::involve(int n, int d)
{
    int rn = 1;
    for (int i=0; i<d; i++)
        rn *= n;
    return rn;
}

UnicodeString super_int::to_string()
{
    UnicodeString str = "";
    UnicodeString unit;
    for (short int i=0; i<rang; i++)
    {
        unit = IntToStr(value[i]);
        if (i != rang-1)
        {
            if (unit.Length() == 1)
                unit = "00" + unit;
            else if (unit.Length() == 2)
                unit = "0" + unit;
        }
        str = unit + str;
    }
    return str;
}


Основная идея - в каждом элементе массива value хранятся данные по трем разрядам. То есть число 123456 будет представлено как value[0] = 456, value[1] = 123, rang = 2. Таким образом можно хранить числа примерно 1E+300. Из математических операторов реализовал только оператор сложения super_int. Каковы перспективы представления дробей такими типами данных? То есть в числителе и знаменателе будут super_int.
PM MAIL   Вверх
FCM
Дата 30.8.2012, 16:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Нитонисе @  30.8.2012,  15:19 Найти цитируемый пост)
При этом работая с double точность теряется, чем больше вычислений мы производим, а при работе с дробями не теряется вообще. 


Если погрешности в отдельных вычислениях знаковые, то при большом количестве вычислений возможна взаимокомпенсация. 

PM MAIL   Вверх
math64
Дата 30.8.2012, 22:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Зачем было предложено хранить числа в виде дробей? чтобы избежать ошибок округления. Как только будет не хватать значащих цифр - будут ошибки округления, и цель не будет достигнута.
Кроме того, дроби помогут только при арифметических действиях, а ты упоминал про синус ...

Вот как должно делаться некоторые операции с неограниченной разрядностью:
Код

typedef unsigned __int64 unit64;
class SuperInt {
int length;
unsigned* data;
SuperInt() { length = 0; data = NULL; }
public:
SuperInt(unsigned n) { data = new int[length = 1]; data[0] = n; }
SuperInt(uint64 n) { data = new int[length = 2]; data[0] = (unsigned)n; data[1] = (unsigned)(n >> 32); }
SuperInt(const SupeInt& n) { length = n.length; data = new int[length]; for(int i=0; i < length; i++) data[i] = n.data[i]; }
SuperInt(const char*s) {
  length = 1;
  data = new unsigned[1];
  data[0] = 0;
  while(*s >= '0' && *s <= '9') {
   *this = *this * 10U + SuperInt((unsigned)(*s-'0'));
  }
}
~SuperInt() { delete data; }
SuperInt operator+(const SupeInt& n) const{
  SuperInt res;
  res.length = max(length, n.length) + 1;
  res.data = new int[length];
  uint64 sum = 0;
  for (int i = 0; i < res.length; i++) {
     if ( i < length) sum += data[i];
     if ( i < n.length) sum += n.data[i];
     res.data[i] = (unsigned)sum;
     sum = sum >> 32;
  }
  return res;
}
SuperInt operator*(const unsigned n) const{
  SuperInt res;
  res.length = length + 1;
  res.data = new int[length];
  uint64 sum = 0;
  for (int i = 0; i < res.length; i++) {
     if ( i < length) sum += (uint64)data[i]*n;
     res.data[i] = (unsigned int)sum;
     sum = sum >> 32;
  }
  return res;
}
SuperInt operator/(const unsigned n) const{
  SuperInt res;
  res.length = length;
  res.data = new int[length];
  uint64 rem = 0;
  for (int i = res.length-1; i >=0 ; i--) {
    rem = rem << 32;
    rem += data[i];
    res.data[i] = (unsigned)(rem / n);
    rem = rem % n;
  }
  return res;
}
unsigned operator%(const unsigned n) const{
  uint64 rem = 0;
  for (int i = res.length-1; i >=0 ; i--) {
    rem = rem << 32;
    rem += data[i];
    rem = rem % n;
  }
  return (unsigned)rem;
}
char* toString(char* buf, int len) const {
  SuperInt tmp = *this;
  for (int i = len - 1; i >= 0; i--) {
     buf[i] = '0' + (tmp%10U);
     tmp = tmp / 10U;
  }
  return buf;
}
};

PM   Вверх
Нитонисе
Дата 31.8.2012, 00:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(math64 @  30.8.2012,  22:15 Найти цитируемый пост)
Как только будет не хватать значащих цифр - будут ошибки округления, и цель не будет достигнута.

Так в том-то и штука, что если есть возможность представить числитель и знаменатель неограниченным количеством знаков (над реализацией надо подумать), то цель будет достигнута. Ведь все операции выполняются с целочисленными типами. По поводу тригонометрии и прочих математических операций - надо подумать. Главное здесь - это принципиальная возможность достижения условно неограниченной точности вычислений с использованием чисел, представленных в виде дроби с условно бесконечным числителем и знаменателем. 

Ну например - неужели не хватит для практических вычислений использование дробей, где числитель и знаменатель могут состоять из миллиона значащих цифр?
PM MAIL   Вверх
math64
Дата 31.8.2012, 07:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Нитонисе @  31.8.2012,  00:22 Найти цитируемый пост)
Ну например - неужели не хватит для практических вычислений использование дробей, где числитель и знаменатель могут состоять из миллиона значащих цифр? 

Ну попробуй, используя только обычный int, без потери точности посчитать сумму первых членов ряда в виде дроби:
1 + 1/2 + 1/3 + 1/5 + 1/7 + 1/11 + 1/13 + ... + 1/p
До какого p хватит точности?

Сложение с неограниченным числом знаком, умножение и деление на обычное число, преобразование к десятичному виду я тебе написал (для чисел без знаков).
Возможно, в коде есть ошибки - писал прямо на экране. Например, нет оператора копирования.
Вычитание делается аналогично сложению.
Умножение в столбик написать тоже очень просто, быстрое умножение - сложнее.
Нужно добавить код для убирания незначащих нулей.
Преобразовывать в десятичный вид и обратно можно сразу по 9 цифр - деля и умножая на 1000000000U.
Дробь можно хранить в виде структуры (знак, числитель, знаменатель);

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


Опытный
**


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

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



Цитата(math64 @  31.8.2012,  07:24 Найти цитируемый пост)
Ну попробуй, используя только обычный int, без потери точности посчитать сумму первых членов ряда в виде дроби:1 + 1/2 + 1/3 + 1/5 + 1/7 + 1/11 + 1/13 + ... + 1/pДо какого p хватит точности?

А зачем использовать обычный int? Надо использовать super_int с неограниченным количеством значащих цифр (ну, конечно, условно неограниченным). С вашим классом я, к сожалению, не разберусь. Либо у меня знаний языка не хватает, либо у вас опечатки. Наример член класса data указывает на неизвестный мне тип unsigned.
PM MAIL   Вверх
math64
Дата 31.8.2012, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



unsigned - это ключевое слово языка C++. эквивалентно unsigned int -  тот же int, но без знака.
Если вам нужно для дробей, знак проще учитывать отдельно, чем реализовавать знаковую арифметику.
data указывает на массив беззнаковых unsigned int длиной length.
В полной реализации нужно две length: сколько выделено и сколько используется.
data[0] - младшие 32 бита, data[1] - следующие 32 бита и т.д.
Реализуется сложенене, вычитание, умножение, деление "в столбик", c "цифрой" unsigned int (беззнакое 32-разрядное целое в диапазоне 0..0xFFFFFFFFu).
При операциях с такими "цифрами" используется typedef unsigned __int64 uint64 - беззнакое 64-разрядное целое в диапазоне 0..0xFFFFFFFFFFFFFFFFuLL - две 32-разрядные "цифры" - чтобы не было переполнение. старшая "цифра" получается сдвигом на 32 бита.

PM   Вверх
Нитонисе
Дата 31.8.2012, 11:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Вот ваш оператор сложения. Прокомментируйте вопросы, которые я закомментировал.
Код

SuperInt operator+(const SupeInt& n) const{
  SuperInt res;
  res.length = max(length, n.length) + 1; // зачем увеличивать рамзер результата на 1? если складывать два числа 2+3 - увеличивать на 1 не нужно
  res.data = new int[length];  // здесь наверное должно быть не length, а res.length?
  uint64 sum = 0;
  for (int i = 0; i < res.length; i++) {
     if ( i < length) sum += data[i];
     if ( i < n.length) sum += n.data[i];
     res.data[i] = (unsigned)sum; // а если в sum(unit64) число больше, чем может хранить unsigned int?
     sum = sum >> 32; // поясните что делает этот код?
  }
  return res;
}

PM MAIL   Вверх
math64
Дата 31.8.2012, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Код

SuperInt operator+(const SupeInt& n) const{
  SuperInt res;
  //Нитонисе: зачем увеличивать рамзер результата на 1? если складывать два числа 2+3 - увеличивать на 1 не нужно
  // А если 0xFFFFFFFF + 1 = 0x1,0x00000000 - была длина 1, стала 2 - рассчитываем на худший результат, заранее на знаем что получится.
  res.length = max(length, n.length) + 1; 
  // Нитонисе: здесь наверное должно быть не length, а res.length?
  // Правильно, опечатка
  res.data = new int[res.length];
  uint64 sum = 0;
  for (int i = 0; i < res.length; i++) {
     if ( i < length) sum += data[i];
     if ( i < n.length) sum += n.data[i];
     // Нитонисе: а если в sum(unit64) число больше, чем может хранить unsigned int?
     // Младшие 32 бита sum записываем в res.data[i], старшие переносим
     res.data[i] = (unsigned)sum; 
     // Нитонисе: поясните что делает этот код?
     // Сдвиг на 32 бита право. Аналогичен делению на 0x100000000UL
     sum = sum >> 32; 
  }
  res.pack(); // убираем незначащие нули
  return res;
}
// убрать незначащие нули
void pack() {
  int oldlength = length;
  while (length > 0) {
     if (data[length-1] != 0)
       break;
       length--;
  }
  if (length != oldLength) {
    unsigned* olddata = data;
    data = new data[length];
    for(int i=0; i < length; i++)
      data[i] = olddata[i];
    delete olddata;
  }
}

PM   Вверх
Нитонисе
Дата 31.8.2012, 16:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



math64, попробовал реализовать ваш класс. Исправил опечатки и мелкие неточности. Не разобрался с вашей функцией toString, мне проще применить для индекации возвращаемое значение типа UnicodeString. Но и без этой функции возникли ошибки утечки памяти. Что-то надо дорабатывать. И еще я так понял надо в класс добавить переменную, хранящую знак числа.

И вообще, насколько я понимаю суть вашего класса в том, что это "супер число" равно сумме чисел массива data? Это ж сколько может понадобиться памяти, чтобы представить число с миллионом значащих цифр?... Мне кажется это не лучший вариант. Я тут переделал свой класс super_int. Число хранится в std::vector<short int> value. Каждый элемент вектора не более 9999. Например число 111122223333 будет записано в таком векторе так value[0] = 3333, value[1] = 2222, value[2] = 1111. Мне кажется перспектив у такой конструкции больше с точки зрения хранения больших чисел с меньшими затратами памяти. На малых числах этот тип скорее будет проигрывать. Ведь если таким образом хранить число 1 уходит 32 байта. Правда я не урезаю вектор под фактическую заполненность. Он ведь вроде резервирует пустые ячейки для записи. 

Это сообщение отредактировал(а) Нитонисе - 31.8.2012, 17:01
PM MAIL   Вверх
math64
Дата 31.8.2012, 18:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



std::vector<> хранит внутри себя массив + небольшую кучку информации - простой массив, однозначно, требует меньше места.
Ты хранишь в каждом short число от 0 до 9999, когда unsigned short может хранить числа от 0 до 65535 - у тебя однозначно, уйдёт больше памяти.
У меня числа хранятся в двоичном виде - компактнее не придумаешь (с условием без потери точности). Но сложнее преобразовывать в десятичную систему.
Я использую unsigned (32 разряда) и unsigned __int64 (64 разряда) вместо unsigned short (16 разрядов) и unsigned - это не даёт экономии памяти, но ускоряет вычисления.
(32 разряда - не менее 9 десятичных цифр, против твоих 8 цифр в двух short)

Утечка памяти - я упоминал, что нужен оператор присваивания. без него будет утечка.

По уму, нужно реализовывать так:
Код

#include <stdio.h>
typedef unsigned __int64 uint64;
inline int max(int a, int b) { return a > b ?a : b; }
class SuperInt {
private: 
  struct Private { // все данные храним в защищенной структуре со счётчиком, позволяющим не копировать данные при присваивании
    int usecnt; // счётчик использования
    int alloc; // выделенная длина массива
    int length; // используемая длина массива
    unsigned data[1]; // данные; реально выделяем память больше, чем на 1 элемент
    static Private* allocate(unsigned n, int len) {
      Private* p = (Private*)new char[sizeof(Private) + sizeof(unsigned)*(len-1)]; // Выделяем память под cnt элементов массива
      p->usecnt = 1;
      p->alloc = len;
      p->length = len;
      for(int i=0; i < len; i++)p->data[i] = n;
      return p;
    }
    void inccnt() { usecnt++; } // увеличение счётчика при повторном использовании (в копирующем конструкторе и операторе присваивания)
    void deccnt() { if (--usecnt == 0) delete[] (char*)this; } // Выделяли память как char[] - удаляем как char[]
  };
  Private* p;
public:
  SuperInt(unsigned n=0, unsigned len = 1) { p = Private::allocate(n, len); }// Конструктор из обычного целого(при len=1)
  SuperInt(const SuperInt& n) { n.p->inccnt(); p = n.p; } // Копирующий конструктор
  SuperInt& operator=(const SuperInt& n) { // Оператор копирования
    if (p == n.p) return *this; // присваивание числа самому себе - ничего не делаем
    p->deccnt(); // если счётчик обнулился - будет удалено
    n.p->inccnt();
    p = n.p;
    return *this;
 }
 ~SuperInt() { // деструктор - данные удаляются, если использовались 1 раз
   //printf("~%d\n",p->usecnt);
   p->deccnt(); p = NULL; 
 }
 SuperInt operator+(const SuperInt& n) const {
   int len = max(p->length, n.p->length) + 1;
   SuperInt res (0, len);
   uint64 sum = 0;
   for(int i =0; i< len; i++) {
      if (i < p->length) sum += p->data[i];
      if (i < n.p->length) sum += n.p->data[i];
      res.p->data[i] = (unsigned)sum;
      sum >>= 32;
   }
   res.pack();
   return res;
 }
 SuperInt operator*(unsigned n) const {
   if (n == 0) return SuperInt(0);
   int len = p->length + 1;
   SuperInt res (0, len);
   uint64 sum = 0;
   for(int i =0; i< len; i++) {
      if (i < p->length) sum += (uint64)p->data[i]*n;
      res.p->data[i] = (unsigned)sum;
      sum >>= 32;
   }
   res.pack();
   return res;
 }
 SuperInt operator/(unsigned n) const {
   int len = p->length;
   SuperInt res (0, len);
   uint64 sum = 0;
   for(int i =len-1; i >= 0; i--) {
      sum <<= 32;
      sum += p->data[i];
      res.p->data[i] = (unsigned)(sum/n);
      sum %= n;
   }
   res.pack();
   return res;
 }
 unsigned operator%(unsigned n) const {
   int len = p->length;
   uint64 sum = 0;
   for(int i =len-1; i >= 0; i--) {
      sum <<= 32;
      sum += p->data[i];
      sum %= n;
   }
   return (unsigned)sum;
 }
 void pack() {
   while(p->length > 0 && p->data[p->length-1] == 0)
     p->length--;
 }
 unsigned toUint32() { return p->length == 0 ? 0  : p->data[0]; }
 double toDouble() {
   double res = 0;
   for(int i = p->length - 1; i >= 0; i--)
     res = res * 0x100000000LL + p->data[i];
   return res;
 }
 void print() {
   if (p->length == 0) { printf("0"); return; }
   if (p->length == 1) { printf("%d", p->data[0]); return; }
   (*this/1000000000U).print();
   printf("%09u", *this%1000000000U);
 }
 void println() {
   print();
   printf("\n");
 }
};
int main() {
SuperInt a = 2U;
SuperInt b = a;
a = 4U;
SuperInt c = a * 10U + b;
unsigned d = (c / 2U).toUint32();
printf("%u\n", d);
SuperInt x = 999999999U;
(x*x.toUint32()*x.toUint32()*x.toUint32()).println();
}

Проверил - код работает.

Учти: я пишу объявление методов класса и реализацию вместе для краткости; тебе их нужно будет разнести на .h и .cpp 
Если пользуешься Visual Studio - можешь рассмотреть возможность перехода на C#.
Там есть BigInteger готовом виде.
BigInteger есть также а Java - с исходниками (алгоритмы можно стянуть оттуда).
Наверняка есть готовая реализация и на C++ - но придётся искать в инете.

Это сообщение отредактировал(а) math64 - 1.9.2012, 20:30
PM   Вверх
Нитонисе
Дата 31.8.2012, 21:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(math64 @  31.8.2012,  18:29 Найти цитируемый пост)
Учти: я пишу объявление методов класса и реализацию вместе для краткости; тебе их нужно будет разнести на .h и .cpp 

Я пишу в C++ Builder XE и разделять код на заголовочный файл и файл реализации необязательно, скинул все в файл h и отредактировал (у вас было много опечаток). Проект скомпилирвал, но при попытке сложить два простых числа выдал ошибку, подсветив строку деструктора, где освобождается память в data. Я не стал дальше разбираться. Конечно ваш метод привлекает тем, что память используется максимально компактно и арифметические действия вроде просто реализуются (у меня сложнее). Возможно и скорость вычислений будет выше (хотелось бы кстати сравнить). Но мне с вашим кодом сложно разобраться  smile  

По поводу памяти выделяемой для моего типа данных. Использую std::vector<short int>. Выделяемая память - sizeof(super_int) = 32 байта. Добавил переменную short int для хранения знака. Размер почему-то стал 40 байт, хотя по идее должен был стать 34. Судя по размеру вектора - при инициализации он зарезервировал 32/2=16 ячеек. А это значит, что максимальное число, котороя я могу в него помсетить без дополнительного выделения памяти - 9999 E+60. Какое максимальное число вы можете разместить в своем SuperInt в таком же объеме памяти (32 байта)?

Это сообщение отредактировал(а) Нитонисе - 31.8.2012, 21:50
PM MAIL   Вверх
Страницы: (6) Все « Первая ... 2 3 [4] 5 6 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

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

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

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

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


 




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


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

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