Юрий-17
Гений
(76476)
5 лет назад
Как я понял, ставится задача сделать класс чисел с разрядностью превышающей разрядность стандартных чисел!?
Ошибку можно найти, но вот вопрос, хороший ли подход применён?
Первый вопрос про класс Infinite_double
Почему вектор содержит int, а не unsigned?
и "запятая" как я понял бежит по десятичным разрядам, а не двоичным!?
Роман ProtocolМыслитель (8562)
5 лет назад
> Как я понял, ставится задача сделать класс чисел с разрядностью превышающей разрядность стандартных чисел!?
Да.
> хороший ли подход применён?
Какие алгоритмы можете предложить для реализации деления?
> Почему вектор содержит int, а не unsigned?
Я предусмотрел спец положение -1 в каком либо разряде на случай ошибки, если в функцию что - то не то пришло или функция как - то не так работает. Тогда можно было бы использовать тип short. Он покороче остальных.
> "запятая" как я понял бежит по десятичным разрядам, а не двоичным
Да, по десятичным. Если двоичные разряды использовать и тип unsigned, то вектор больше памяти будет занимать чем при десятичных разрядах и тип unsigned. Если двоичные разряды использовать то vector < char >.
Чем предпочтительнее использовать число в двоичном предст-ении?
Роман ProtocolМыслитель (8562)
5 лет назад
Я перегрузил и отладил перегрузку для операторов + -* > < <= >= == для обработки экземпляров класса Infinite_double и vector < int >.
Деление сложновато перегружать.
Роман ProtocolМыслитель (8562)
5 лет назад
Чтобы оправдать использование двоичных разрядов по объёму занимаемой памяти контейнером нужно подобрать тип данных как можно меньший, но не принимающий 10 позиций. Иначе по объёму памяти хранения десятичная запись предпочтительней, на мой взгляд. Это по одному параметру. Я не знаю, почему Вы предлагаете двоичную запись, может это быстрее считать будет ПК. Опишите преимущества использования двоичных разрядов.
Роман ProtocolМыслитель (8562)
5 лет назад
Я ввёл множество шаблонов. При объявлении экземпляров класса Infinite_double просто определяем шаблон класса, который пропишет все T во всех vector < T > мантиссы в коде.
Роман ProtocolМыслитель (8562)
5 лет назад
Уже попались -1, значит ещё ошибка есть.
Это в случае 131072 / 17 ответ 770-1.-1-1-1-1-1 вместо 7710.11764.
-1 выбрасывает функция Division_Digit, если цифра более 9, что недопустимо.
template < typename T >
int Division_Digit(vector < T > &v2, vector < T > v1)
{
int rez = -1;
if (v2 == v1)
{
rez = 1;
v2.clear();
}
else
{
rez = 0;
for (unsigned u = 0; u < 9; ++u)
{
if (v2 >= v1)
{
v2 = v2 - v1;
Clear_null_v(v2);
++rez;
}
else
{
break;
}
}
if (v2 >= v1)
{
rez = -1;
}
}
return rez;
}
Алексей Полюдов
Профи
(870)
5 лет назад
Каждый десятичный знак представлен элементом массива типа int ?
А что бы тогда просто не делать ascii арифметику? на массивах байтов? Я видел такие имплементации.
Далее, если интересно поучиться делать big number math посмотрите ка это сделано в cpython, или в gmplib.
Роман ProtocolМыслитель (8562)
5 лет назад
> Каждый десятичный знак представлен элементом массива типа int ?
Я шаблон ввёл. Теперь при объявлении экземпляра класса Infinite_double < T > можно задать тип разрядов мантиссы.
> на массивах байтов?
Как указать тип байт? Я смотрел в стандартных типах C++ его не нашёл.
Чебуратор
Мыслитель
(8449)
5 лет назад
Чем long double не угодил? Точность мантиссы 2^-112, это достаточно много, даже не знаю, где может понадобиться такая точность. Для отображение кол-ва чисел после запятой нужно обращаться к методам cout. Представление в виде строки это конечно забавно, но очень медленно - тем более деление очень дорогая операция и ее по возможности нужно заменять умножением. Советую вам также глянуть формат IEEE 754, как зерно для размышлений. Вообще при реализации сабжа задача сводиться к повторению битов мантиссы, начиная с момента когда наступает периодическое повторение, просто копировать дальше по массиву, естественно работать нужно с двоичным представлением.
Роман ProtocolМыслитель (8562)
5 лет назад
> Чем long double не угодил? Точность мантиссы 2^-112, это достаточно много, даже не знаю, где может понадобиться такая точность.
Число Пи хотел почесать. Да, подход у меня не совершенен.
> Представление в виде строки
Это инициализация экземпляра строкой происходит. Далее строки не используются входе вычислений.
> наступает периодическое повторение
А как его отловишь? Ведь может одна цифра повторяться бесконечно в дробной части, а может две одинаковые цифры рядом стоят и будут приняты за повтор.
> естественно работать нужно с двоичным представлением
Почему? Все это говорят, а никто пока не рассказал.
https://pastebin.com/T5jExsTv
Пишу код перегрузки деления Infinite_double на Infinite_double. Infinite_double - это класс, описанный мною, содержащий приватные поля
vector < int > mantissa (мантисса числа с плавающей запятой) и
unsigned long fract (количество цифр справа от запятой, то есть в дробной части числа)
а также ряд конструкторов и методов класса.
Я представляю число (мантиссу в частности) как набор цифр vector < цифра > + длина дробной части.
Clear_null(e1); - метод, удаляющий из мантиссы незначащие нули слева (в любом случае) и справа (пока не завершится проход дробной части).
Equalizer(e1, e2); - выравниватель дробной части. У экземпляров, передаваемых в этот метод будут одинаковы fract. То есть числа e1 и e2 будут иметь после запятой (справа от запятой) одинаковое количество цифр. Недостающие цифры мантиссы заполняются 0.
Например
e1 представляет число 84,99
e2 представляет число 603,90445
После Equalizer(e1, e2);
e1 представляет число 84,99000
e2 представляет число 603,90445
Division_Digit(temp, v2) - узнаёт сколько раз укладывается вектор v2 (как число) в вектор temp (как число). Это целочисленное деление с отбросом остатка максимум до 9 включительно.
Например, temp = 64, v2 = 15, тогда Division_Digit(temp, v2) = 4.
Я написал, работает вроде норм. делит - результаты правильные, но иногда запятая не туда встаёт. Например код
string st2 = "110";
Infinite_double id2(st2);
string st1 = "9";
Infinite_double id1(st1);
Infinite_double id3;
id3 = id2 / id1;
id3.Show_Number();
cout << endl;
выдаёт 1.222222222 вместо 12.22222222 А иногда правильно запятая ставится. Помогите сделать перегрузку /, чтобы во всех ситуациях - при любых делимом и делителе деление работало правильно и выдавало верный результат деления.
Спасибо тем, кто поможет!