С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/18: Рейтинг темы: голосов - 18, средняя оценка - 4.83
 Аватар для SerVal
37 / 36 / 9
Регистрация: 16.04.2015
Сообщений: 283

Длинная арифметика с базой 2^32

29.12.2018, 15:06. Показов 3728. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Решил посмотреть, будет ли быстрее, чем с базой 1 000 000 000
Почитал идею. Длинная арифметика от Microsoft: https://habr.com/post/207754/ база 2^32

Создал класс:

C++
1
2
3
4
5
6
7
8
9
10
11
12
// 2^32 = 4294967296
static const unsigned long long BASE = 4294967296;
static const unsigned int BASE_DIGITS = 9;
#define BASE_TYPE uint32_t
 
struct BigInt {
 
public:
    std::vector<BASE_TYPE> a;
    int sign;
.....
}
Сделал конструкторы из uint32_t b uint64_t. Например:
C++
1
2
3
4
5
6
7
8
9
10
void BigInt_from_uint64(unsigned long long x) 
{
    int sign = positive;
    std::vector<uint32_t> a;
 
    unsigned long long v = x;
    for (; v > 0; v >>= 32)
        a.push_back(v % BASE);
        return;
}
для uint64_t = 9223372036854775807 получается вектор { 4294967295, 2147483647} // ok.
Но загрузка из строки того же числа - "9223372036854775807" и вывод на экран - никак.
Помогите с функцией ввода/вывода:

C++
1
2
3
4
5
6
7
bool parseDecimalString(const std::string s0 = "9223372036854775807")
{
    std::string s = s0;
    std::vector<uint32_t> a;
    int sign = 1;
// ???
return true;
Ну и при выводе на экран показывает всё что угодно, но не исходную строку.
Может кто-нибудь покажет, как надо сделать?
*в Инете про длинную арифметику с основанием 2^32 ничего не нашёл.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
29.12.2018, 15:06
Ответы с готовыми решениями:

Длинная арифметика
Алгоритмы всех операций в принципе уже готовы (длина числа ограничивается только ресурсами ПК). Осталось только подобрать качественный...

Длинная арифметика
:senor: Здраствуйте, пишу модуль длинной математики. В принципе, работоспособность у него положительная. Но в силу моей неопытности меня...

Длинная арифметика: найти остаток от деления большого числа (до 10^100 000) на 12
Здравствуйте, вопрос по поводу задачки, хочу попытаться реализовать решение на плюсах, а не на питоне. Суть такая: надо найти остаток от...

13
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
29.12.2018, 20:31
Цитата Сообщение от SerVal Посмотреть сообщение
Может кто-нибудь покажет, как надо сделать?
Простой вариант делается аналогично алгоритму перевода из одной системы счисления в другую. В одном случае ты переводишь из 10-сс в https://www.cyberforum.ru/cgi-bin/latex.cgi?2^{32}-сс, в другом - обратно.
0
 Аватар для SerVal
37 / 36 / 9
Регистрация: 16.04.2015
Сообщений: 283
07.01.2019, 06:06  [ТС]
В общем, ничего лучшего не придумал, кроме как преобразовать входную с десятичными цифрами в двоичную строку.
А двоичную строку распарсить в вектор по базе 2^32

Функция преобразования строки в вектор с базой 2^32

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
      // parse decimal string. delimiters: ' ',  '\r', '\n, ','  skip all digits after '.'
 
     // копируем входную строку убирая разделители между цифрами
    const BigInt BigInt::ParseDecimalString(const std::string& s0) {
 
        std::string s;
        for (size_t i = 0; i < s0.size(); i++) 
        {
            if (
                (s0[i] == ' ')  ||
                (s0[i] == '\r') ||
                (s0[i] == '\n') ||
                (s0[i] == ',') 
                )  continue; // skip '\r', '\n, ','  ' ' 
            if (s0[i] == '.')
                break;
            s += s0[i];
        }
 
       // преобразуем строку в двоичную
 
        std::string bin_str = BigInt::DecimalStringToBinaryString(s); 
 
        BigInt res; // для возвращаемого результата
 
       // преобразуем двоичную строку в вектор<uint32> с базой 2^32
        
       for (long long i = bin_str.size() - 1, v = BASE; i >= 0; --i, v <<= 1) {
 
            int x = bin_str[i] - '0';
 
            if (v == BASE) {
                v = 1;
                res.a.push_back(x);
            }
            else res.a.back() += (x)*v;
        }
 
        res.trim(); // убрать нули слева 
        return res;
    }
Для ввода/вывода маленьких цифр пойдёт.

C++
1
2
3
4
5
6
7
8
 
  BigInt A = "123 1234 12345 123456 1234567";
  A.printInfo();
 
  Результат:
  big integer : 1231234123451234561234567
  number of decimal digits = 25
  number of segments       = 3
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
07.01.2019, 06:42
Цитата Сообщение от SerVal Посмотреть сообщение
std::vector<BASE_TYPE>
Если заменить на std::basic_string<BASE_TYPE>, то на небольших числах не будет выделения динамической памяти.
0
 Аватар для SerVal
37 / 36 / 9
Регистрация: 16.04.2015
Сообщений: 283
07.01.2019, 07:12  [ТС]
rat0r, спасибо за отклик. Но непонятно, где можно поменять вектор на строку?
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
07.01.2019, 07:14
SerVal,
C++
1
2
3
4
struct BigInt {
 
public:
    std::basic_string<BASE_TYPE> a;
0
 Аватар для SerVal
37 / 36 / 9
Регистрация: 16.04.2015
Сообщений: 283
07.01.2019, 07:39  [ТС]
Тут вот какая засада вылезла:

Во первых, для умножения пришлось использовать не преобразование Фурье, а Карацубу.
Умножение Фурье у меня сделано для базы 10. То есть, по одной десятичной цифре в элементах вектора.
Карацубу распараллелил на 2 потока. Помогло только для маленьких чисел.
Для больших - Фурье в 2 раза быстрее.

Ну и во вторых, для больших чисел пришлось отказаться от показа результатов на экране.
Вычисление числа десятичных цифр в векторе по базе 2^31 практически не дождаться.
Раньше так было:
C++
1
2
3
4
5
6
7
8
9
10
TestBigInt.exe -factorial 1 000 000
 
Intel(R) Core(TM)2 Quad CPU    Q9650  @ 3.00GHz
 
Calculating 1000000!
 big integer :  8 ... 0
 number of decimal digits = 5565709
 number of segments       = 618413
 
time : 49.108 sec.
А теперь можно посмотреть только затраченное время. В общем, пока преимуществ от базы 2^32 не видно.

Добавлено через 6 минут
rat0r, так это не числа будут вычисляться, а строки. Такое пойло уже есть.
Кажется, называется "GNU Multiple Precision Arithmetic Library". От неё вообще ничего не дождёшься.
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
07.01.2019, 07:42
Цитата Сообщение от SerVal Посмотреть сообщение
так это не числа будут вычисляться, а строки.
Шта?!
Ну тогда и вектор нельзя использовать, с ним не числа вычисляются, а вектора.
0
 Аватар для SerVal
37 / 36 / 9
Регистрация: 16.04.2015
Сообщений: 283
07.01.2019, 08:00  [ТС]
rat0r, умножение, деление, вычитание строк давно известно. И признано абсолютно тухлой идеей. Собственно говоря, это сложение и вычитание столбиком по базе 10(как учат в детском саду или школе).
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
07.01.2019, 08:07
SerVal, ты хотя бы пытался прочитать (на "понять" я уже не надеюсь), что я написал в #4?
0
 Аватар для SerVal
37 / 36 / 9
Регистрация: 16.04.2015
Сообщений: 283
07.01.2019, 08:45  [ТС]
rat0r, скорее всего у нас немного разные понятия что такое небольшие числа.
Большие числа начинаются от 100 миллионов цифр.
Вот вычисление небольшого числа - всего 6 миллионов цифр.
C++
1
2
3
4
5
6
7
8
9
10
11
12
>TestBigInt.exe -generate Mp40
 
Intel(R) Core(TM)2 Quad CPU    Q9650  @ 3.00GHz
 
 
Generating Mersenn prime Mp40 = 2^20996011-1
 
 big integer :  125976895 ... 855682047
 number of decimal digits = 6320430
 number of segments       = 702270
 
time : 22.69 sec.
22 секунды для небольшого числа - это многовато. Поэтому и ищу способы ускорить.
Хотя бы раз в 10. Или чтобы производительность возрастала пропорционально числу ядер процессора.

Добавлено через 6 минут
*FFT на ГПУ я уже попробовал. Ничего интересного.
Вся производительность съедается пересылкой массивов на ГПУ и обратно.
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
07.01.2019, 23:50
Цитата Сообщение от SerVal Посмотреть сообщение
не преобразование Фурье, а Карацубу.
Карацубу можно использовать в паре с умножением "в столбик", реализованным при помощи SIMD-инструкций.
При этом большую роль играет управление памятью в алгоритме. В идеале память должна выделяться ровно один раз.
0
 Аватар для SerVal
37 / 36 / 9
Регистрация: 16.04.2015
Сообщений: 283
08.01.2019, 03:58  [ТС]
nonedark2008, спасибо за отклик.
Да, Карацуба распараллеленный на два потока, используется как оператор умножения.
А память я формально не выделяю. push_back(), pop_back(), resize() и eraze() сами с этим справляются.

Про SIMD-инструкции: никогда не пробовал. Теоретически, вещь заманчивая. А практически, я ещё не добавил все операторы в класс BigInt. Для работы с int32_t, uint32_t? int64_t.. пока операторов нетути. То есть, всё через BigInt.

Да и деление сейчас делаю методом Ньютона-Рафсона. Оно примерно в 30 раз медленее умножения.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
>TestBigInt.exe -div Mp27
 -- division test --
 Проверка умножения и деления.
 Generating number Mp27
 
 big integer :  854509824 ... 011228671
 number of decimal digits = 13395
 number of segments       = 1391
 
 time : 26.392 sec.
 
 Умножение. B = A*A time : 0.003 sec.
 Деление.   C = B/A time : 0.083 sec.
Это на Core(TM)2 Quad CPU Q9650 @ 3.00GHz
************
Пока мы тут пушбэкаем, народ уже нашёл 50-е и 51-е простые числа Мерсена.
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
08.01.2019, 16:33
Цитата Сообщение от SerVal Посмотреть сообщение
А память я формально не выделяю. push_back(), pop_back(), resize() и eraze() сами с этим справляются.
Я к тому, что хоть ты сам память и не дергаешь, но все твои push, pop и прочие скорее всего сжирают кучу времени, из-за необходимости постоянно выделять/перевыделять память. Особенно это должно быть заметно в Карацубе, где плодится огромное количество объектов.

Добавлено через 2 часа 48 минут
Цитата Сообщение от SerVal Посмотреть сообщение
Про SIMD-инструкции: никогда не пробовал. Теоретически, вещь заманчивая
В свое время я реализовывал согласно этому документу (расширение файла .pdf). Стоит учесть, что по техническим причинам там используется база https://www.cyberforum.ru/cgi-bin/latex.cgi?2^{29}. Сейчас под современные платформы можно найти и что-нибудь поновее.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
08.01.2019, 16:33
Помогаю со студенческими работами здесь

длинная арифметика
Долгое время бьюсь как составить программу по этой теме в интернете искал нашел это for (int i=(int)s.length(); i&gt;0; i-=9) if (i...

Длинная арифметика
Подскажите, пожалуйста, где ошибки в программе. Еще хотелось бы узнать, правильно ли реализована длинная арифметика и на правильном ли я...

Длинная арифметика
Вот условие задачи: Во время исследований, посвященных появлению жизни на планете Олимпия, учеными было сделано несколько сенсационных...

Длинная арифметика
Программка уже почти готова, единственное неправильно находит остаток при делении По заданию: Надо ввести 2-ва целых числа неогран....

Длинная арифметика
http://www.acmp.ru/index.asp?main=task&amp;id_task=103 Как решить эту задачу? С помощью чего, и в чем смысл решения длянной...


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и источниками (напряжения, ЭДС и тока). Найти токи и напряжения во всех элементах. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru