Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.62/26: Рейтинг темы: голосов - 26, средняя оценка - 4.62
2 / 2 / 0
Регистрация: 26.01.2016
Сообщений: 39
1

Разность римских чисел без перевода в десятичную систему

06.12.2019, 14:43. Показов 4682. Ответов 18
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день! Мне в университете задали РГЗ на разность двух римских чисел. Казалось бы, это сделать легко, путём перевода каждого числа в десятичное, найти разность и записать обратно в римский вид. Однако вся сложность заключается в том, что пользоваться переводом в десятичное число нельзя. Дорогие друзья! Подскажите пожалуйста, в каком направлении копать? Как примерно это можно реализовать? Код я смогу написать сам, мне бы только идею
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.12.2019, 14:43
Ответы с готовыми решениями:

Перевода вещественного числа из шестиричной в десятичную систему счисления
Собственно, не могу найти функцию перевода вещественного числа из 6 сс в 10ую(у меня есть функция...

Составить программу перевода заданного числа в десятичную систему счисления
Дано целое число в двоичной системе счисления, т.е. последовательность цифр 0 и 1. Составить...

Сформировать новый массив путем перевода элементов начального массива в десятичную систему
Здравствуйте, у меня есть такое задание: Дан массив что складывается из чисел двоичной системы...

Сформировать новый массив путем перевода значений элементов исходного массива в десятичную систему счисления
Необходимо ввести массив, состоящий из 9 элементов (девять двузначных чисел в восьмеричной системе...

18
859 / 448 / 112
Регистрация: 06.07.2013
Сообщений: 1,491
06.12.2019, 16:45 2
На ум приходит такое:
Сначала нужно научиться вычитать 1 из любого римского числа
затем для 2 римских чисел A и B в цикле пока (B = B - 1) != 0
вычитать из A единицу
1
2 / 2 / 0
Регистрация: 26.01.2016
Сообщений: 39
06.12.2019, 17:06  [ТС] 3
Так-то идея хорошая. А если в цекле сделать так, что мы уменьшаем число A до тех пор, пока у нас A != B, счётчик и будет ответ. А потом этот ответ перевести в римское число
0
859 / 448 / 112
Регистрация: 06.07.2013
Сообщений: 1,491
06.12.2019, 17:11 4
Да, еще и лучше даже
0
2 / 2 / 0
Регистрация: 26.01.2016
Сообщений: 39
06.12.2019, 17:20  [ТС] 5
Придумал ещё лучше. Сделать цикл, пока A != B, ответом будет являться счётчик. В цикле добавлять единичку к числу B. Спасибо большое за ответ, дома попробую реализовать
0
6579 / 4564 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
06.12.2019, 17:24 6
Цитата Сообщение от voltara13 Посмотреть сообщение
Так-то идея хорошая. А если в цекле сделать так, что мы уменьшаем число A до тех пор, пока у нас A != B, счётчик и будет ответ. А потом этот ответ перевести в римское число
Там ещё сравнение нужно будет сделать, т.к. вычитать надо из большего или прибавлять к меньшему
0
2 / 2 / 0
Регистрация: 26.01.2016
Сообщений: 39
06.12.2019, 17:27  [ТС] 7
Если к числу B прибавлять, то я примерно знаю, как это сделать
0
14 / 11 / 3
Регистрация: 16.10.2019
Сообщений: 95
06.12.2019, 17:32 8
Когда же я буду иметь счастье созерцать решение?
0
2 / 2 / 0
Регистрация: 26.01.2016
Сообщений: 39
06.12.2019, 17:36  [ТС] 9
Сегодня - завтра постараюсь сделать
0
2 / 2 / 0
Регистрация: 26.01.2016
Сообщений: 39
07.12.2019, 18:02  [ТС] 10
Что-то не получается у меня сделать. Работает только с супер-маленькими числами. Например VIII и V. Всё-таки сделать так, чтобы число VIIII (так как мы к B добавляем I) трансформировалось в IX - очень затруднительно
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 <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
int operation(char *a, char *b)
{
    int answer = 0;
    for (; strcmp(a, b); answer++) 
    {
        b[strlen(b)] = 'I';
        
    }
    return answer;
}
 
void print(int number)
{
    char result[1000]{'\0'};
    const int values[] = {1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000};
    const char *symbols[] = {"I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM", "M"};
    int counter = sizeof(symbols) / sizeof(symbols[0]) - 1;
    while (counter >= 0)
    {
        while (number >= values[counter])
        {
            number -= values[counter];
            strcat(result, symbols[counter]);
        }
        counter--;
    }
    cout << result << endl;
}
 
int main()
{
    char a[255];
    char b[255];
    gets(a);
    gets(b);
    print(operation(a, b));
    system("pause");
    return 0;
}
0
6579 / 4564 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
07.12.2019, 18:08 11
Цитата Сообщение от voltara13 Посмотреть сообщение
Что-то не получается у меня сделать. Работает только с супер-маленькими числами. Например VIII и V. Всё-таки сделать так, чтобы число VIIII (так как мы к B добавляем I) трансформировалось в IX - очень затруднительно
Ну да, просто так не сделаешь - там позиционная система.
Цитата Сообщение от voltara13 Посмотреть сообщение
Однако вся сложность заключается в том, что пользоваться переводом в десятичное число нельзя.
А ты не переводи в десятичное, переводи в бинарное - int (компьютеры вроде с ними работают). По-моему, там по-другому никак.
0
2 / 2 / 0
Регистрация: 26.01.2016
Сообщений: 39
07.12.2019, 18:15  [ТС] 12
Тоже думал об этом. Хотя не уверен, что это разрешено) Но попробую. Спасибо

UPD
По-моему, чтобы перевести римское число в бинарное - нужно всё равно перевести сначала в десятичное, разве нет?
0
6579 / 4564 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
07.12.2019, 18:19 13
Цитата Сообщение от voltara13 Посмотреть сообщение
Тоже думал об этом. Хотя не уверен, что это разрешено) Но попробую. Спасибо
Что-то я сомневаюсь, что древние римляне что-то суммировали в этой системе. Наверное тоже только время записывали и всё.
0
2 / 2 / 0
Регистрация: 26.01.2016
Сообщений: 39
09.12.2019, 12:19  [ТС] 14
Попытался написать программу, которая будет считать XI - III, где III - число B. У нас в цикле получается следующее:
III (добавляем I, к циклу добавляется 1) - получается IIII (через условие меняется IIII на IV, добавляем I, к циклу добавляется 1) - получается IVI (через условие меняется IVI на V, добавляем I, к циклу добавляется 1) - получается VI и так далее, пока не дойдём до XI. Счётчик цикла - и есть ответ, который нужно перевести в римское число (что происходит без проблем). Идея по сути рабочая, но программа не работает, останавливается на первом цикле и пишет Segmentation fault. Не могу найти в чём проблема. Есть ли у вас идеи, как можно оптимизировать код? Здесь ещё нет многих циклов для чисел побольше, однако сейчас не об этом речь. Прошу помочь!
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
126
127
128
#include <iostream>
#include <cstring>
using namespace std;
int operation(char *a, char *b)
{
    int answer = 0;
    for (; strcmp(a, b); answer++)
    {
        b[strlen(b)] = 'I';
        for (int i = 0; i < strlen(b); i++)// VV -> X
        {
            if (b[i] == 'V' && b[i + 1] == 'V')
            {
                b[i] = 'X';
                for (int j = i + 1; j < strlen(b); j++)
                    b[j] = b[j + 1];
            }
        }
        for (int i = 0; i < strlen(b); i++)// LL -> C
        {
            if (b[i] == 'L' && b[i + 1] == 'L')
            {
                b[i] = 'C';
                for (int j = i + 1; j < strlen(b); j++)
                    b[j] = b[j + 1];
            }
        }
        for (int i = 0; i < strlen(b); i++)// DD -> M
        {
            if (b[i] == 'D' && b[i + 1] == 'D')
            {
                b[i] = 'M';
                for (int j = i + 1; j < strlen(b); j++)
                    b[j] = b[j + 1];
            }
        }
        for (int i = 0; i < strlen(b); i++)// IIII -> IV
        {
            if (b[i] == 'I' && b[i + 1] == 'I' && b[i + 2] == 'I' && b[i + 3] == 'I')
            {
                b[i + 1] = 'V';
                b[i + 2] = 0;
                for (int j = i + 2; j < strlen(b); j++)
                    b[j] = b[j + 1];
            }
        }
        for (int i = 0; i < strlen(b); i++)// XXXX -> XL
        {
            if (b[i] == 'X' && b[i + 1] == 'X' && b[i + 2] == 'X' && b[i + 3] == 'X')
            {
                b[i + 1] = 'L';
                b[i + 2] = 0;
                for (int j = i + 2; j < strlen(b); j++)
                    b[j] = b[j + 1];
            }
        }
        for (int i = 0; i < strlen(b); i++)// CCCC -> CD
        {
            if (b[i] == 'C' && b[i + 1] == 'C' && b[i + 2] == 'C' && b[i + 3] == 'C')
            {
                b[i + 1] = 'D';
                b[i + 2] = 0;
                for (int j = i + 2; j < strlen(b); j++)
                    b[j] = b[j + 1];
            }
        }
        for (int i = 0; i < strlen(b); i++)// IVI -> V
        {
            if (b[i] == 'I' && b[i + 1] == 'V' && b[i + 2] == 'I')
            {
                b[i] = 'V';
                b[i + 1] = 0;
                for (int j = i + 1; j < strlen(b); j++)
                    b[j] = b[j + 1];
            }
        }
        for (int i = 0; i < strlen(b); i++)// VIV -> IX
        {
            if (b[i] == 'V' && b[i + 1] == 'I' && b[i + 2] == 'V')
            {
                b[i] = 'I';
                b[i + 1] = 'X';
                b[i + 2] = 0;
                for (int j = i + 2; j < strlen(b); j++)
                    b[j] = b[j + 1];
            }
        }
        for (int i = 0; i < strlen(b); i++)// IXI -> X
        {
            if (b[i] == 'I' && b[i + 1] == 'X' && b[i + 2] == 'I')
            {
                b[i] = 'X';
                b[i + 1] = 0;
                for (int j = i + 1; j < strlen(b); j++)
                    b[j] = b[j + 1];
            }
        }
    }
    return answer;
}
 
void print(int number)
{
    char result[1000]{'\0'};
    const int values[] = {1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000};
    const char *symbols[] = {"I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM", "M"};
    int counter = sizeof(symbols) / sizeof(symbols[0]) - 1;
    while (counter >= 0)
    {
        while (number >= values[counter])
        {
            number -= values[counter];
            strcat(result, symbols[counter]);
        }
        counter--;
    }
    cout << result << endl;
}
 
int main()
{
    char a[255] = {0};
    char b[255] = {0};
    gets(a);
    gets(b);
    print(operation(a, b));
    return 0;
}
0
2 / 2 / 0
Регистрация: 26.01.2016
Сообщений: 39
11.12.2019, 19:41  [ТС] 15
Ребят! Вопрос всё ещё актуален! Прошу помощи
0
случайный прохожий
2934 / 1951 / 606
Регистрация: 20.07.2013
Сообщений: 5,160
12.12.2019, 00:20 16
Лучший ответ Сообщение было отмечено voltara13 как решение

Решение

https://educontest.net/ru/3656... %B0%D1%85/
5. Вычисления с римскими числами
Часто римская запись чисел считается чем-то крайне громоздким и неудобным, особенно для вычислений в ней. Иногда даже утверждается, что римляне именно из-за нее почти ничего не достигли в математике в отличие от греков. Хотя греки тоже пользовались непозиционной системой, лишь в деталях отличавшейся от римской. Считать же римляне умели очень хорошо, иначе не могли бы строить подземные акведуки или весьма сложные здания. И не только благодаря абаку, похожему на счеты, без него тоже было бы не так уж сложно вручную выполнять арифметические вычисления.
Поскольку известно, что вплоть до позднего средневековья была широко распространена ныне забытая запись чисел римскими цифрами: без принципа вычитания, только сложением всех символов, например, обозначать 4 не IV а IIII; 90 не XC, а LXXXX, тогда сложение чисел совсем просто, достаточно собрать вместе цифры всех чисел, а затем упростить результат.
Например, 647 + 179 = DCXXXXVII + CLXXVIIII = D CC LXXXXX X VV IIIII I = D CC LL XX V I = DCCCXXVI. То же самое действие можно выполнить сначала столбиком, как мы привыкли с арабскими числами, а затем упростить результат:
+ D C XXXX V II
___ C L XX V IIII
D CC L LX X VI

D CC L LX X VI = DCCCXXVI

При вычитании аналогично будем удалять знаки из уменьшаемого, при необходимости сперва "подробнее" расписав его.
Например,
500 – 263 = D – CC LX III = CCCC LXXXX VIIIII – CC LX III = CC XXX VII.
_CCCC L XXXX V IIIII
___CC L X III_
CC XXX V II

https://spravochnick.ru/inform... hisleniya/
Разность римских чисел без перевода в десятичную систему



https://nsportal.ru/ap/library... chisleniya
Сложение и вычитание Сложить два римских числа не очень сложно: XIX + XXVI = XXXV Последовательность выполнения сложения такова: а) IX+VI: I после V "уничтожает" I перед X, поэтому в результате получаем XV; б) X+XX=XXX, если добавить еще один X, получим XXXX, или XL. Сложность вычитания римских чисел приблизительно такая же. Но чтобы из 500 вычесть 263, 500 надо сначала разложить на более мелкие составляющие и «сократить» повторяющиеся в уменьшаемом и вычитаемом знаки: D - CCLXIII = CCCCLXXXXVIIIII - CCLXIII = CCXXXVII
2
2 / 2 / 0
Регистрация: 26.01.2016
Сообщений: 39
12.12.2019, 13:29  [ТС] 17
Спасибо большое! Примерно понял как сделать
0
2 / 2 / 0
Регистрация: 26.01.2016
Сообщений: 39
22.12.2019, 09:13  [ТС] 18
Программу сделал. Если кому-то нужно, то вот:
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
 
int find_N(char *str, const char *fnd)
{
    int N = -1;
    for (int i = 0; i < strlen(str); i++)
    {
        for (int j = 0; j < strlen(fnd); j++)
        {
            if (j == strlen(fnd) - 1 && str[i + j] == fnd[j]) //Находим подстроку в строке
            {
                N = i;
                break;
            }
            if (str[i + j] == fnd[j])
                continue;
            else
                break;
        }
        if (N == i)
            break;
    }
    return N;
}
 
void _sorting(char *str)
{
    const char rome_nums[8] = {'M', 'D', 'C', 'L', 'X', 'V', 'I', '\0'}; //Составляем приоритетность римских чисел для строки
    int begin = 0;
    int cup;
    for (int i = 0; i < strlen(rome_nums); i++)
    {
        for (int j = begin; j < strlen(str); j++)
        {
            if (str[j] != rome_nums[i])
                continue;
            if (j == 0 || str[j - 1] == rome_nums[i]) //Исключаем нахождение нужных символов в начале строки
            {
                begin++;
                continue;
            }
            for (int k = j; k > begin; k--) //Смещаем символ к началу строки
            {
                cup = str[k];
                str[k] = str[k - 1];
                str[k - 1] = cup;
            }
            begin++;
        }
    }
}
 
void _replace(char *str, const char *fnd, const char *chng)
{
    int N = find_N(str, fnd);
    if (N == -1)
        return; //Выходим из функции, если подстрока не нашлась
    char end[100];
    int end_check = strlen(str) - N - strlen(fnd);
    if (end_check > 0) //Исключаем возможность выхода за пределы
    {
        //Находим, что идет после заменяемой подстроки
        strcpy_s(end, 100, str);
        _strrev(end);
        end[end_check] = '\0';
        _strrev(end);
    }
    str[N] = '\0';
    strcat_s(str, 100, chng); //Подставляем необходимую подстроку
    if (end_check > 0)
        strcat_s(str, 100, end);
}
 
void _subtraction(char *str1, char *str2)
{
    for (int i = 0; i < strlen(str1); i++) 
    {
        for (int j = 0; j < strlen(str2); j++) 
            if (str1[i] == str2[j])           
            {
                for (int k = i, len = strlen(str1); k < len; k++)
                    str1[k] = str1[k + 1];
                for (int k = j, len = strlen(str2); k < len; k++)
                    str2[k] = str2[k + 1];
                i--, j--; //Элементы сдвинуты на один. Нужно вернуть счётчики на шаг назад
            }
    }
    if (!strlen(str1) && strlen(str2))
    {
        cout << "Первое введённое число меньше второго" << endl;
        system("pause");
        exit(0);
    }
}
 
void _resdidual(char *x1, char *x2)
{
    while (strlen(x2))
    {
        _replace(x1, "IV", "IIII");
        _replace(x1, "IX", "VIIII");
        _replace(x1, "XL", "XXXX");
        _replace(x1, "XC", "LXXXX");
        _replace(x1, "CD", "CCCC");
        _replace(x1, "CM", "DCCCC");
        _replace(x2, "IV", "IIII");
        _replace(x2, "IX", "VIIII");
        _replace(x2, "XL", "XXXX");
        _replace(x2, "XC", "LXXXX");
        _replace(x2, "CD", "CCCC");
        _replace(x2, "CM", "DCCCC");
 
        _replace(x1, "M", "DD");
        _replace(x1, "D", "CCCCC");
        _replace(x1, "C", "LL");
        _replace(x1, "L", "XXXXX");
        _replace(x1, "X", "VV");
        _replace(x1, "V", "IIIII");
        _replace(x2, "M", "DD");
        _replace(x2, "D", "CCCCC");
        _replace(x2, "C", "LL");
        _replace(x2, "L", "XXXXX");
        _replace(x2, "X", "VV");
        _replace(x2, "V", "IIIII");
 
        _subtraction(x1, x2); //Из массива str1 вычитаем совпдающие элементы с массивом str2, путём сдвига элемнтов массива влево
        _sorting(x1); //Сортируем полученный массив
 
        _replace(x1, "IIIII", "V");
        _replace(x1, "VV", "X");
        _replace(x1, "XXXXX", "L");
        _replace(x1, "LL", "C");
        _replace(x1, "CCCCC", "D");
        _replace(x1, "DD", "M");
        _replace(x1, "VIIII", "IX");
        _replace(x1, "IIII", "IV");
        _replace(x1, "LXXXX", "XC");
        _replace(x1, "XXXX", "XL");
        _replace(x1, "DCCCC", "CM");
        _replace(x1, "CCCC", "CD");
    }
}
 
bool _check(char *x1, char *x2)
{
    bool check = false;
    const char rome_nums[8] = {'M', 'D', 'C', 'L', 'X', 'V', 'I', '\0'};
    for (int i = 0; i < strlen(x1); i++)
    {
        for (int j = 0; j < strlen(rome_nums); j++)
            if (x1[i] == rome_nums[j])
            {
                check = true;
                break;
            }
        if (check) break;
    }
    if (!check) return check;
    check = false;
    for (int i = 0; i < strlen(x2); i++)
    {
        for (int j = 0; j < strlen(rome_nums); j++)
            if (x2[i] == rome_nums[j])
            {
                check = true;
                break;
            }
        if (check) break;
    }
    return check;
}
int main()
{
    setlocale(LC_ALL, "rus");
    char x1[100] = {0};
    char x2[100] = {0};
    cout << "Введите 1-е слагаемое в формате MDCLXVI: ";
    gets(x1);
    cout << "Введите 2-е слагаемое в формате MDCLXVI: ";
    gets(x2);
    if (!_check(x1, x2))
    {
        cout << "Неправильный ввод" << endl;
        system("pause");
        return 0;
    }
    _resdidual(x1, x2); //Вызываем функцию разности
    cout << "x1 - x2 = ";
    if (!strlen(x1))
    {
        cout << "Нуль" << endl;
        system("pause");
        return 0;
    }
    puts(x1);
    system("pause");
}
1
0 / 0 / 0
Регистрация: 27.12.2020
Сообщений: 1
27.12.2020, 19:08 19
voltara13, привет, а у тебя не осталось блок-схем к программе?
0
27.12.2020, 19:08
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.12.2020, 19:08
Помогаю со студенческими работами здесь

Функции для перевода чисел из девятичной системы в десятичную
Надо на С++ Кто какие функции знает?

Написать программу для перевода чисел из двоичной системы в десятичную
Написать программу для перевода чисел из двоичной системы в десятичную

Написать рекурсивный алгоритм перевода из двоичной системы счисления в десятичную ( из восьмеричной и шестнадцатеричной в десятичную)
Написать рекурсивный алгоритм перевода из двоичной системы счисления в десятичную ( из восьмеричной...

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


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

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru