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

Потестируйте скорость работы класса больших чисел

19.08.2015, 17:47. Показов 5920. Ответов 100
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Ребятки, сделал себе небольшой классик для больших чисел.
Типа того:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
static const long long BASE = 1000000000;
static const int BASE_DIGITS = 9;
 
enum sign { positive = 1, negative = -1 };
 
struct BigInt {
 
    std::vector<int> a;
    int sign;
 
    // constructors
    BigInt() : sign(positive) { } // default constructor
}
Ну и хотелось бы сравнить, насколько он медленно работает.
C++
1
2
3
4
5
6
7
8
>TestBigInt.exe -factorial 100000
--- factorial test ---
Calculating 100000!
 big integer :  2824 ... 0
 number of decimal digits = 456574
 number of segments       = 50731
 
time : 10.961 sec.
Это на Intel Quad Q9550 2,8 GHz
Если у кого есть результаты, приведите их пожалуйста.

*мне нравятся большие числа и женщины, но с числами интереснее.
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
19.08.2015, 17:47
Ответы с готовыми решениями:

Скорость работы id и класса
Что быстрее работает id или класс? Бывают такие моменты, что думаешь, а что лучше использовать. Да понятно если стиль повторяется много...

Обертка класса, наследование - скорость работы
1. Есть класс MyServer(использует класс TcpListener), как только MyServer ловит какое то соединение, он возвращает ссылку на экземпляр...

Конструктор класса больших чисел
Добрый вечер! Решаю следующую задачу: нужно создать класс Huge, который будет использовать массив из 50 элементов для хранения целых...

100
 Аватар для SerVal
37 / 36 / 9
Регистрация: 16.04.2015
Сообщений: 283
25.08.2015, 19:45  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от zer0mail Посмотреть сообщение
А можно глянуть на код для радеона?
Сложение 2-х больших чисел на ГПУ.
(видеадаптер не выбираем. Зацапываем первый попавшийся - Radeon, nVidia или Intel GPU)
Кликните здесь для просмотра всего текста

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#pragma once
#ifndef BIGINT_AMP
#define BIGINT_AMP
 
#include "BigInt.h"
#define NOMINMAX
 
#include <amp.h>
#include <iostream>
#include <assert.h>
#include <amp_math.h>
#include <ctime>
 
using namespace std;
using namespace concurrency;
 
#ifndef BASE
#define BASE (long long) 1000000000
#endif
 
// Показываем название ускорителя.
void print_accelerator_description()
{
    accelerator acc;
    accelerator_view av = acc.create_view();
    std::wstring core_device_name = av.accelerator.description;
    std::wcout << L"Accelerator: " << core_device_name << std::endl;
}
 
// Вспомогательная для переноса carry на ЦПУ
bool has_carry(std::vector<INT32>& vec)
{
    for (size_t i = 0; i < vec.size(); i++)
    {
        if (vec[i] != 0)
            return true;
    }
    return false;
}
//*******************************************************
// Складываем на ГПУ числа A и B. Переносы делаем на ЦПУ :(
BigInt gpu_add(const BigInt& numA, const BigInt& numB)
{
    std::vector<INT32> a(numA.a.begin(), numA.a.end());
    std::vector<INT32> b(numB.a.begin(), numB.a.end());
    std::vector<INT32> c, carry;
    size_t max_size = std::max(numA.a.size(), numB.a.size());
 
    // создаём 3 числа на ЦПУ и массив переносов carry.  Результат будет в "c".
    a.resize(max_size);
    b.resize(max_size);
    c.resize(max_size + 1);
    carry.resize(max_size + 1);  // флаги переноса
 
    // создаём их представление на ГПУ. Сами данные на ГПУ не копируем.
    array_view<INT32, 1> avA(a.size(), &a[0]);
    array_view<INT32, 1> avB(b.size(), &b[0]);
    array_view<INT32, 1> avC(c.size(), &c[0]); avC.discard_data();
    array_view<INT32, 1> avCarry(carry.size(), &carry[0]); avCarry.discard_data();
 
    //std::cout << " числа A и B в ГПУ созданы. Складываем." << endl;
    parallel_for_each(avA.extent, [=](index<1> idx) restrict(amp)
    {
        avC[idx] = avA[idx] + avB[idx];
 
        if (avC[idx] >= BASE)
        {
            avCarry[idx + 1] = 1;
            avC[idx] -= BASE;
        }
        else avCarry[idx + 1] = 0;
    });
 
    // синхронизируем массивы. ГПУ->ЦПУ
    avC.synchronize();      // результат без переносов
    avCarry.synchronize();  // массив переносов
 
    // делаем переносы на ЦПУ. 
    while (has_carry(carry))
    {
        for (int i = 1; i < carry.size(); i++)
        {
            if (carry[i] != 0)
            {
                c[i]++;
                carry[i] = 0;
            }
        }
    }
    // переносы сделаны. 
    // удалить нуль впереди, если он есть.
    if (c[c.size() - 1] == 0)
        c.pop_back();
 
    BigInt res;
    res.a = c;
    return res;
}
#endif // BIGINT_AMP


int main():
Кликните здесь для просмотра всего текста

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
42
43
44
int main(int argc, char *argv[])
{
    setlocale(LC_CTYPE, "russian");
    //runTest(argc, argv);
    print_accelerator_description();
    
    double total_time = (double)clock() / CLOCKS_PER_SEC;
    BigInt a; a.Load("M48.txt");
    
    BigInt b = a; 
    std::cout << " Числа готовы. " << endl;
    std::cout << " time : " << (double)clock() / CLOCKS_PER_SEC - total_time << " sec." << std::endl << std::endl;
 
    BigInt result, result1;
 
    std::cout << "Сложение на ЦПУ." << endl;
    total_time = (double)clock() / CLOCKS_PER_SEC;
    for (int i = 0; i < 100; i++)
    {
        result = a + b;
    }
    std::cout << " time : " << (double)clock() / CLOCKS_PER_SEC - total_time << " sec." << std::endl << std::endl;
 
    std::cout << "Сложение на ГПУ." << endl;
    total_time = (double)clock() / CLOCKS_PER_SEC;
    for (int i = 0; i < 100; i++)
    {
        result1 = gpu_add(a, b);
    }
    std::cout << " time : " << (double)clock() / CLOCKS_PER_SEC - total_time << " sec." << std::endl << std::endl;
    
    result.printInfo();  std::cout << endl;
    result1.printInfo(); std::cout << endl;
 
    if (result == result1)
    {
        std::cout << "Результаты совпадают." << endl;
    }
 
    else
    {
        std::cout << "Результаты не совпадают!" << endl;
    }
}


Output:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>TestBigInt.exe
Accelerator: AMD Radeon HD 6800 Series
 Числа готовы.
 time : 0.403 sec.
 
Сложение ЦПУ.
 time : 4.292 sec.
 
Сложение ГПУ.
 time : 8.915 sec.
 
 big integer :  1 ... 448571902
 number of decimal digits = 17425171
 number of segments       = 1936131
 
 big integer :  1 ... 448571902
 number of decimal digits = 17425171
 number of segments       = 1936131
 
Результаты совпадают.
1
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
25.08.2015, 20:06
SerVal, боюсь, что куча выделений памяти что на ЦПУ, что на GPU играет не в пользу производительности. Что показывает анализ?
0
 Аватар для SerVal
37 / 36 / 9
Регистрация: 16.04.2015
Сообщений: 283
25.08.2015, 20:36  [ТС]
Цитата Сообщение от nonedark2008 Посмотреть сообщение
Что показывает анализ?
Ну, никакого анализа пока нетути, только вчера натяпал.
Смотрю загрузку видеоадаптера программкой GPU-Z. Загрузка - 10-15%
Похоже, основное время тратится на учёт переносов - это делает ЦПУ.
Нужна какая-нибудь идея, как сделать переносы на ГПУ.

Для анализа делаю программульку, которая создаст 2 файла с циферками.
Типа
A.txt "111111111...." и B.txt "222222....". По 30-40 миллионов цифр в каждом.
Если их складывать, переносов не будет, то есть для сложения будет использоваться чисто ГПУ.
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
25.08.2015, 21:49
Цитата Сообщение от SerVal Посмотреть сообщение
Нужна какая-нибудь идея, как сделать переносы на ГПУ.
Боюсь, что если задачу нельзя разбить на много маленьких подзадачь, то от GPU толку не будет.
Переносы можно обрабатывать только последовательно, тут уж сложно извернуться.
Я бы лучше забил на GPU, сделал бы BASE максимально возможным и избавился бы от всех условных переходов.
0
317 / 268 / 61
Регистрация: 12.10.2011
Сообщений: 434
25.08.2015, 22:03
Цитата Сообщение от _Ivana Посмотреть сообщение
golatin, спасибо, смешно Даже смешнее упоминаемой тут формулы Стирлинга
Не понял, а что здесь смешного? Нахождение значения синуса за ТРИ такта процессора? Предложите аналог...
0
25.08.2015, 22:11

Не по теме:

golatin, смешно то, что это здесь абсолютно не в тему :) Здесь энтузиасты обсуждают реализацию длинной целочисленной арифметики с базовым набором операций - ну хочется людям сделать собственный велосипед и посоревноваться с существующими реализациями. Вы же предлагаете заценить как ловко и быстро, но приближенно считается синус или любая другая функция через интерполяцию по таблице :) Аналогов я вам могу предложить несколько, но в данной теме это оффтоп.

0
 Аватар для SerVal
37 / 36 / 9
Регистрация: 16.04.2015
Сообщений: 283
25.08.2015, 22:19  [ТС]
Ребятки, может у меня Radeon такой зачуханный? (ЦПУ - "народный квад" )

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Сложение больших чисел на ЦПУ и ГПУ.
Accelerator: AMD Radeon HD 6800 Series
 
 создаём 2 файла с двойками и тройками ~ по 87 Мегабайт.
 файлы 222.txt и 333.txt созданы.
 загружаем числа из файлов 222.txt и 333.txt
 числа готовы.
 time : 20.033 sec.
 
Сложение на ЦПУ.
 time : 14.261 sec.
 
Сложение на ГПУ.
 time : 31.183 sec.
 
 big integer :  555555555 ... 555555555
 number of decimal digits = 90000000
 number of segments       = 10000000
 
 big integer :  555555555 ... 555555555
 number of decimal digits = 90000000
 number of segments       = 10000000
Результаты совпадают.
У кого видеоадаптер поприличнее? не покажете результат сложения?
файл TestGpuAddition.rar прилагаю. (разархивировать и запустить к окне консоли).
Вложения
Тип файла: rar TestGpuAddition.rar (27.1 Кб, 6 просмотров)
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
25.08.2015, 22:24
Что-то у тебя не так при вычислениях на GPU, процессор (CPU) "жрёт" по полной.
Миниатюры
Потестируйте скорость работы класса больших чисел  
0
317 / 268 / 61
Регистрация: 12.10.2011
Сообщений: 434
25.08.2015, 22:35
Цитата Сообщение от _Ivana Посмотреть сообщение
golatin, смешно то, что это здесь абсолютно не в тему Здесь энтузиасты обсуждают реализацию длинной целочисленной арифметики с базовым набором операций - ну хочется людям сделать собственный велосипед и посоревноваться с существующими реализациями. Вы же предлагаете заценить как ловко и быстро, но приближенно считается синус или любая другая функция через интерполяцию по таблице Аналогов я вам могу предложить несколько, но в данной теме это оффтоп.

Не по теме:

ОК:) Не понял сразу...
Бесит, когда приходят на работу подобные студенты, а затем узнают, что их велосипеды ВДРУГ не работают... При чем же молчат, - типо ВСЕ знают; нет, чтобы спросить сразу же, так молчат, - затем за них все переделывать (юношеский максимализм, - он такой%-))

0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
25.08.2015, 22:36
SerVal, я не знаю как работает AMP, но технология OpenCL определяет у меня два устройства: GPU и эмуляция GPU через CPU. Может в AMP такая же ситуация и твой код работает через эмуляцию?
0
 Аватар для SerVal
37 / 36 / 9
Регистрация: 16.04.2015
Сообщений: 283
25.08.2015, 22:46  [ТС]
Цитата Сообщение от castaway Посмотреть сообщение
Что-то у тебя не так при вычислениях на GPU, процессор (CPU) "жрёт" по полной.
Ну, это в цикле 100 сложений. Конечно странно, посмотрю. Спасибо.

*nVidia, кстати, выпустила библиотеку длинной арифметики для своих адаптеров.
народ, правда, утверждает, что она всего в 1,5 -2 раза быстрее, чем на ЦПУ. И загружает ЦПУ на 15-20%.

Добавлено через 6 минут
Цитата Сообщение от castaway Посмотреть сообщение
как работает AMP
AMP, по сути дела DirectX. И по загрузке видеоадаптера видно: ~20%.
У меня есть ещё GTX-460. Сейчас Radeon вытащу и впихну nВидию.
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
25.08.2015, 22:50
Цитата Сообщение от SerVal Посмотреть сообщение
AMP, по сути дела DirectX.
Про это я успел прочитать. Просто не работал с этой технологией.
0
 Аватар для SerVal
37 / 36 / 9
Регистрация: 16.04.2015
Сообщений: 283
25.08.2015, 23:20  [ТС]
Вытащил Radeon и впихнул nВидию GTX-460. Побыстрее маленько, но не айс.

C++
1
2
3
4
5
6
7
8
9
10
11
12
>TestGpuAddition.exe
 
Сложение больших чисел на ЦПУ и ГПУ.
Accelerator: NVIDIA GeForce GTX 460
 
Сложение на ЦПУ.
 time : 13.854 sec.
 
Сложение на ГПУ.
 time : 30.206 sec.
 
Результаты совпадают.
0
 Аватар для SerVal
37 / 36 / 9
Регистрация: 16.04.2015
Сообщений: 283
31.08.2015, 08:20  [ТС]
Ребятки, помогите разбрать строку, чтобы можно было сгенерировать само число.
Строка вида 3*4^5-6 , причём не все операции могут присутствовать.
Если возведения в степень нет, то последнюю операцию(+-) можно игнорировать.

Все цифры - unsigned long long.

C++
1
2
3
4
5
6
7
8
>TestBigInt.exe -generate 12345
 
Generating number 12345
 big integer :  12345
 number of decimal digits = 5
 number of segments       = 1
 
time : 0.009 sec.
Для 4^5-6 , хоть и криво, но сделал.
C++
1
2
3
4
5
6
7
8
>TestBigInt.exe -generate "4^5-6"
 
Generating number 4^5-6
 big integer :  1018
 number of decimal digits = 4
 number of segments       = 1
 
time : 0.012 sec.
// generate BibInt from string: "M23", "M35", "12345", "12^34-56" or "12^34+56"
const BigInt BigInt::generate_number(const std::string& s);
Кликните здесь для просмотра всего текста

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
    const BigInt BigInt::generate_number(const std::string& s)
    {
        BigInt res = 0; // результат
 
        // first try parse Mersenn numbers "M1", "M2" ...
        long long messen_exp = BigInt::mersenExp(s);
        if (messen_exp != 0)
        {
            res = BigInt::mersenNumber(s);
            return res;
        }
 
        std::string str_base;
        std::string str_exp;
        int last_operand_sign = 0; // "+" or "-"
 
        std::string str_last_digit;
 
        // находим экспоненту
        int exp_pos = 0;
        int i;
        for (i = 0; i < s.length(); i++)
        {
            if (s[i] == '^')
                break;
        }
 
        if (i != s.length())
            exp_pos = i;
 
        // находим базу
        for (int i = 0; i < s.length(); i++)
        {
            if (s[i] == '^')
                break;
            str_base += s[i];
        }
        //std::cout << " str_base = " << str_base << std::endl;
 
        unsigned long long base;
        try{ base = std::stoull(str_base); }
        catch (...)
        {
            std::cout << "Cannot convert string '" << str_base << "' to unsigned long long" << std::endl;
            return res;
        }
 
        if (exp_pos == 0) // экспоненты нет. base просто какое-то число.
        {
            res = base;
            return res;
        }
 
        // экспонента есть.
        for (i = exp_pos + 1; i < s.length(); i++)
        {
            if (s[i] == '+')
            {
                last_operand_sign = 1;
                break;
            }
            if (s[i] == '-')
            {
                last_operand_sign = -1;
                break;
            }
 
            str_exp += s[i];
        }
 
        unsigned long long exp;
        try{ exp = std::stoull(str_exp); }
        catch (...)
        {
            std::cout << "Cannot convert exponent '" << str_exp << "' to unsigned long long" << std::endl;
            return res;
        }
 
        // last operand "+" or "-"
        if (last_operand_sign == 0) // "+" or "-" not exists
        {
            res = BigInt::power(base, exp);
            return res;
        }
 
        int last_digit_pos = s.length();
        int last_digit_n_chars = 0;
 
        for (i = s.length() - 1; i >= 0; i--)
        {
 
            if ((s[i] == '+') || (s[i] == '-'))
            {
                break;
            }
            last_digit_pos--;
            last_digit_n_chars++;
        }
 
        for (i = 0; i < last_digit_n_chars; i++)
        {
            str_last_digit += s[last_digit_pos++];
        }
        //std::cout << " str_last_digit " << str_last_digit << std::endl;
 
        unsigned long long last_digit;
        try{ last_digit = std::stoull(str_last_digit); }
        catch (...)
        {
            std::cout << "Cannot convert last digit '" << str_exp << "' to unsigned long long" << std::endl;
            return res;
        }
 
        if (last_operand_sign < 0)
        {
            res = BigInt::power(base, exp) - last_digit;
        }
 
        if (last_operand_sign > 0)
        {
            res = BigInt::power(base, exp) + last_digit;
        }
        //std::cout << " Ok." << std::endl;
        return res;
    }


Всё Ок, но нужен ещё множитель впереди... и чёта никак.

Добавлено через 9 минут
Ну, чтобы в программе можно было писать:
C++
1
2
3
4
int main(int argc, char *argv[])
{
    BigInt a = BigInt::generate_number("3*7^11-1");
}
0
196 / 197 / 120
Регистрация: 27.05.2011
Сообщений: 545
31.08.2015, 09:03
Может регуляркой забацать? Будет код короче.
Perl
1
^(\d+)\*(\d*)\^(\d*)([-+]?)(\d*)$
Сейячас попытаюсь накрапацать что-нибудь с помощью regex…

Хм… неужели он не поддерживает комментарии внутри регулярных выражений?
0
 Аватар для SerVal
37 / 36 / 9
Регистрация: 16.04.2015
Сообщений: 283
31.08.2015, 09:14  [ТС]
Цитата Сообщение от mymedia Посмотреть сообщение
Может регуляркой забацать? Будет код короче
Да, конечно. Это всё равно быстро.
Главное, чтобы я смог сгенерить число, типа того:
int result = num1*(num2^num3) +-num4;

note: ^ - это степень.
0
196 / 197 / 120
Регистрация: 27.05.2011
Сообщений: 545
31.08.2015, 10:12
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
#include <array>
#include <cmath>
#include <iostream>
#include <regex>
#include <stdexcept>
#include <string>
 
struct invalid_format
    : public std::invalid_argument
{
    invalid_format(const std::string& s) : std::invalid_argument(s) { }
};
 
int generate_number(const std::string& str)
{
    using namespace std;
    regex regular { R"(^(\d+)(?:\*(\d+))?(?:\^(\d+))?([-+]\d+)?$)" };
    smatch results;
    if (!regex_match(str, results, regular)) {
        throw invalid_format("'" + str + "' cannot convert to integer array");
    }
 
    // Значения по умолчанию для отсутствующих компонент выражения
    array<int, 4> defaults = { 0, 1, 1, 0 };
    array<int, 4> out;
    for (int i = 0; i < 4; i++) {
        if (results[i + 1] != "") {
            out[i] = std::stoi(results[i + 1]);
        } else {
            out[i] = defaults[i];
        }
    }
 
    return out[0] * pow(out[1], out[2]) + out[3];
}
 
int main() {
    std::string s;
    std::cin >> s;
    std::cout << generate_number(s) << std::endl;
}
Только, честно, я не разобрался с вашим классом BigInt, но, надеюсь, вам не составит труда получить его из компонент массива out.

Пример работы:
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
user@netbook:~$ ./a.out 
2*10^2+12
212
user@netbook:~$ ./a.out 
3*2^10
3072
user@netbook:~$ ./a.out 
1234
1234
user@netbook:~$ ./a.out 
123*100
12300
user@netbook:~$ ./a.out 
qwerty
terminate called after throwing an instance of 'invalid_format'
  what():  'qwerty' cannot convert to integer array
Аварийный останов (сделан дамп памяти)
user@netbook:~$
1
 Аватар для SerVal
37 / 36 / 9
Регистрация: 16.04.2015
Сообщений: 283
31.08.2015, 12:12  [ТС]
mymedia, спасибо. Попробовал, чёта тут не то.

C++
1
 std::string s = "1*10^2+1";
Результат: a = 101 // Ok.

C++
1
 std::string s = "10^2+1";
Результат: a = 11 //
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
31.08.2015, 12:33
Цитата Сообщение от SerVal Посмотреть сообщение
Попробовал, чёта тут не то.
Тебе скорее всего нужно написать нормальный парсер для арифметических выражений.
Тут либо рекурсивным спуском все считать, либо через обратную польскую запись например.
Хотя всегда можно взять готовую библиотеку.
0
196 / 197 / 120
Регистрация: 27.05.2011
Сообщений: 545
31.08.2015, 12:35
Лучший ответ Сообщение было отмечено SerVal как решение

Решение

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
42
43
#include <array>
#include <cmath>
#include <iostream>
#include <regex>
#include <stdexcept>
#include <string>
 
struct invalid_format
    : public std::invalid_argument
{
    invalid_format(const std::string& s) : std::invalid_argument(s) { }
};
 
int generate_number(const std::string& str) throw(invalid_format)
{
    using namespace std;
    const regex regular { R"(^(?:(\d+)\*)?(\d+)(?:\^(\d+))?([-+]\d+)?$)" };
    // Значения по умолчанию для отсутствующих компонент выражения
    constexpr array<int, 4> defaults = { 1, 0, 1, 0 };
 
    smatch results;
    if (!regex_match(str, results, regular)) {
        throw invalid_format("'" + str + "' cannot convert to integer");
    }
 
    array<int, 4> out;
    for (int i = 0; i < 4; i++) {
        if (results[i + 1] != "") {
            out[i] = stoi(results[i + 1]);
        } else {
            out[i] = defaults[i];
        }
    }
 
    return out[0] * pow(out[1], out[2]) + out[3];
}
 
int main() {
    using namespace std;
    string s;
    getline(cin, s);
    cout << generate_number(s) << endl;
}
Теперь вроде работет как нужно:
Code
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
user@netbook:~$ g++-5 -std=c++11 tmp.cpp
user@netbook:~$ ./a.out 
10^2+1
101
user@netbook:~$ ./a.out 
2*10^2+12
212
user@netbook:~$ ./a.out 
3*2^10
3072
user@netbook:~$ ./a.out 
1234
1234
user@netbook:~$ ./a.out 
123*100
12300
user@netbook:~$ ./a.out 
2*15+4
34
user@netbook:~$ ./a.out 
2^8
256
user@netbook:~$ ./a.out 
qwerty
terminate called after throwing an instance of 'invalid_format'
  what():  'qwerty' cannot convert to integer
Аварийный останов (сделан дамп памяти)
user@netbook:~$
Теперьрегулярка тербует, чтобы вторая компонента всегда была обязательной (а не первая, как вначале было), а значение по умолчинию для неё просто для единообразия.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
31.08.2015, 12:35
Помогаю со студенческими работами здесь

Создание класса для работы с массивами чисел
Сделать класс для работы с массивами чисел. У класса должно быть 5 метода. 1. Получение первого элемента массива. 2....

Создать класс для работы с одномерным массивом целых чисел. Разработать следующие элементы класса:
Создать класс для работы с одномерным массивом целых чисел. Разработать следующие элементы класса: Свойства: • возвращающее размерность...

Разработать класс "Массив больших чисел", который состоит из объектов класса "Большие целые числа". Найти сумму элементов массива.
Разработать класс &quot;Массив больших чисел&quot;, который состоит из объектов класса &quot;Большие целые числа&quot;. Найти сумму элементов...

ArrayList, скорость копирования больших структур, копирование по ссылке
Добрый день, Возникла следующая ситуация, в программе есть ArrauList на базе сложной и громосткой структуры данных. И есть ф-и, которые...

Реализация класса "Вектор" для работы с массивом чисел
Помогите решить задачу пожалуйста) Объявите класс &quot;Вектор&quot;, полем которого является массив чисел, а методами: очистка вектора; добавление...


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

Или воспользуйтесь поиском по форуму:
80
Ответ Создать тему
Новые блоги и статьи
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка SDL3 и Box2D из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru