Форум программистов, компьютерный форум, киберфорум
Python: Решение задач
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/18: Рейтинг темы: голосов - 18, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 19.11.2022
Сообщений: 3

Текстовый калькулятор

19.11.2022, 09:14. Показов 3802. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Нужна помощь с заданием:
Написать калькулятор для строковых выражений вида '<число> <операция> <число>', где <число> - не отрицательное целое число меньшее 100, записанное словами, например "тридцать четыре", <арифмитическая операция> - одна из операций "плюс", "минус", "умножить". Результат выполнения операции вернуть в виде текстового представления числа. Пример calc("двадцать пять плюс тринадцать") -> "тридцать восемь"
Добавить возможность оперировать с дробями (правильными и смешанными). Реализовать поддержку сложения, вычитания и умножения, дробей. Результат операций не должен представлять неправильную дробь, такие результаты нужно превращать в смешанные дроби. Пример: calc("один и четыре пятых плюс шесть седьмых ") -> "два и двадцать три тридцать пятых"
Заранее спасибо
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
19.11.2022, 09:14
Ответы с готовыми решениями:

Текстовый калькулятор
Помогите с задачей. Есть файл calc.txt, в котором хранятся записи вида 100 + 34 23 / 4 то есть ОПЕРАНД_1 ОПЕРАЦИЯ ОПЕРАНД_2,...

Текстовый калькулятор
нужна помощь с заданием в университете: Написать калькулятор для строковых выражений вида '&lt;число&gt; &lt;операция&gt;...

Задача по Python Текстовый калькулятор
Прошу помощи в задаче, начал решение, но совершенно не знаю как выполнить до конца её. Заранее спасибо! with open('calc.txt') as f: ...

10
Эксперт Python
 Аватар для Red white socks
4523 / 1899 / 336
Регистрация: 18.01.2021
Сообщений: 3,489
19.11.2022, 09:30
Цитата Сообщение от Makiavell1 Посмотреть сообщение
Нужна помощь с заданием:
Какой помощи вы ждете?
Писать полностью калькулятор за вас никто не будет
0
0 / 0 / 0
Регистрация: 19.11.2022
Сообщений: 3
19.11.2022, 10:34  [ТС]
вовсе нет, я просто не знаю, как решить вторую часть задания.
первая часть такая:
Python
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
s = input()
dct_1 = {v: k for k, v in enumerate('один два три четыре пять шесть семь восемь девять десять одиннадцать двенадцать тринадцать четырнадцать пятнадцать шестнадцать семнадцать восемнадцать девятнадцать'.split(), 1)}
dct_10 = {v: 10*k for k, v in enumerate(' двадцать тридцать сорок пятьдесят шестьдесят семьдесят восемьдесят девяносто'.split(), 2)}
dct_100 = {v: 100*k for k, v in enumerate('сто двести триста четыреста пятьсот шестьсот семьсот восемьсот девятьсот'.split(), 1)}
dct_1000 = {v: 1000*k for k, v in enumerate('одна тысяча,две тысячи,три тысячи,четыре тысячи,пять тысяч,шесть тысяч,семь тысяч,восемь тысяч,девять тысяч'.split(','), 1)}
dct_ = {'плюс': '+', 'минус': '-', 'умножить': '*'}
 
dct = {**dct_1, **dct_10, **dct_100, **dct_1000, **dct_}
 
d = 0
for elem in s.split():
    if type(dct[elem]) == int:
        d += dct[elem]
    else:
        res = d
        op = dct[elem]
        d = 0
 
if op == '+':
    res += d 
elif op == '-':
    res -= d 
else:
    res *= d 
 
dct_text = {v: k for k, v in dct.items()}
 
txt = []
if res < 0:
    txt.append('минус')
    res *= -1
elif res == 0:
    txt.append('ноль')
 
k = 1000
while k:
    if res > k-1:
        if res > 20:
            txt.append(dct_text[res//k*k])
            res %= k 
        else:
            txt.append(dct_text[res])
            k = 0
    k //= 10
 
print(' '.join(txt))
а дальше затуп

Добавлено через 7 минут
просто проблема заключается в написании кода. Если алгоритм я могу представить, то с написанием самого кода сложности
0
Эксперт Python
 Аватар для Red white socks
4523 / 1899 / 336
Регистрация: 18.01.2021
Сообщений: 3,489
19.11.2022, 11:45
Цитата Сообщение от Makiavell1 Посмотреть сообщение
просто проблема заключается в написании кода. Если алгоритм я могу представить,
Задача с парсингом строки мне представляется сложной именно с алгоритмической точки зрения.
Если алгоритм у вас готов - расскажите, код написать помогут
0
0 / 0 / 0
Регистрация: 19.11.2022
Сообщений: 3
19.11.2022, 13:54  [ТС]
как я думаю, по аналогии ввести значения знаменателя (добавляя окончания) (и числителя (от 1 до 9 новые)), при этом число будет получаться путем написания '/', то есть знак будет являться текстом. Затем пойдет операция, как сейчас в коде(+, -, *). При умножении перемножаем отдельно числители и знаменатели. Если операция + или -, то идет проверка равенства знаменателей. если знаменатели не равны, то ищем их наименьшее общее кратное. Домножаем числитель и знаменатель на число, равное делению НОК на знаменатель. Затем выполняем действие операции в числителях(то есть +, -).
Но с целыми частями тяжеловато, я не в курсе, можно ли при написании "два и три пятых", "два" представить как 5/5*2. И как быть с "и". Если, например, числитель больше знаменателя, то мы считаем результат целочисленного деления числителя на знаменатель и переводим результат в текст. Может при вводе целой части, мы должны обратиться к тому, что едет за ней, и знаменатель умножить на эту целую часть и сложить с числителем. В общем, описать трудно, но я попробовал.
0
Эксперт Python
 Аватар для Red white socks
4523 / 1899 / 336
Регистрация: 18.01.2021
Сообщений: 3,489
19.11.2022, 15:23
Makiavell1, в задаче только один нетривиальный момент - преобразование текста в число. И основная трудность, что строки с целыми читаются иначе, чем строки с дробями. Все остальное - арифметика и число в текст особого труда не представляет: делаете класс Rational, где и определяете методы и представление объектов класса. Класс храктеризуется двумя взаимно простыми числами, а целая часть выделяется уже при выводе результата в методах __str__ или __repr__.
Начинайте прописывать класс: сложение, умножение и прочие арифметические действия, а парсинг оставим уже напоследок.
0
78 / 73 / 19
Регистрация: 18.05.2021
Сообщений: 287
19.11.2022, 22:02
Python
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
symbols = {
        "плюс": "+",
        "минус": "-",
        "умножить": "*",
        "разделить": "/",
        "делить": "/",
        "корень": "**0.5",
        "скобка": "|",
        "запятая": "."
        }
 
numbers = {
        "один": "1",
        "одна": "1",
        "два": "2",
        "две": "2",
        "три": "3",
        "четыре": "4",
        "пять": "5",
        "шесть": "6",
        "семь": "7",
        "восемь": "8",
        "девять": "9",
        
        "десять": "10",
        "одиннадцать": "11",
        "двенадцать": "12",
        "тринадцать": "13",
        "четырнадцать": "14",
        "пятнадцать": "15",
        "шестнадцать": "16",
        "семнадцать": "17",
        "восемнадцать": "18",
        "девятнадцать": "19",
        
        "двадцать": "20",
        "тридцать": "30",
        "сорок": "40",
        "пятьдесят": "50",
        "шестьдесят": "60",
        "семьдесят": "70",
        "восемьдесят": "80",
        "девяносто": "90",
        
        "сто": "100",
        "двести": "200",
        "триста": "300",
        "четыреста": "400",
        "пятьсот": "500",
        "шестьсот": "600",
        "семьсот": "700",
        "восемьсот": "800",
        "девятьсот": "900",
        
        "тысяча": "1000",
        "тысячи": "1000",
        "тысяч": "1000",
        "миллион": "1000000",
        "миллионов": "1000000",
        "миллиард": "1000000000",
        "миллиардов": "1000000000",
        "миллиарда": "1000000000"
        }
 
def solve(text):
    a = text_to_numbers(text)
    answer = "Ответ. " + str(round(eval(a), 4)).replace(".", ", запяат+ая, ")
    return answer
 
def text_to_numbers(text):
    new_text = []
    for i in text:
        if i in symbols.keys():
            new_text.append(symbols[i])
        elif i in numbers.keys():
            new_text.append(numbers[i])
    
    new_text = numbers_from_pieces(new_text)
    
    while "None" in new_text:
        new_text.remove("None")
        
        
    
    return list_of_numbers_to_string(new_text)
 
def list_of_numbers_to_string(ls):
    string = ""
    brackets = "("
    for i in ls:
        if i == "|":
            string += brackets
            if brackets == "(":
                brackets = ")"
            else:
                brackets = "("
        else:
            string += i
    return string
 
def numbers_from_pieces(text):
    new_text = []
    number = None
    for i in text:
        if number == None and i not in symbols.values():
            number = int(i)
        else:
            if i in symbols.values():
                new_text.append(str(number))
                new_text.append(i)
                number = None
            else:
                if number < int(i):
                    number *= int(i)
                else:
                    number += int(i)
    new_text.append(str(number))
    return new_text
 
class Comand:
    def __init__(self):
        self.comands = {
                ("посчитай", ): solve,
                ("считай", ): solve
                }
        self.activ_frase = "Калькулятор активен."
        
    def solve(self, frase):
        return solve(frase)
Я писал так, код весьма посредственный, но работает. На вход принимается фраза вида "два умножить на пять плюс три минус сорок точка пять", которая воспринимается как "2*5 + 3 - 40.5"

П.С. Для вычисления выражения вызывается функция solve(), на всякую обвязку можно не обращать внимания, код писался для голосового помощника. Может чем нибудь поможет.

Добавлено через 1 минуту
П.П.С Всё что отсутствует в ключах просто игнорится.

Добавлено через 11 минут
Фраза вводится списком (фраза, разбитая на слова).
Т.е. например так:
Python
1
2
3
4
5
6
7
a = "сто сорок пять минус сто умножить на два".split()
print(solve(a))
 
# результат:
#
# Ответ. -55
# >>>
0
Эксперт Python
 Аватар для Red white socks
4523 / 1899 / 336
Регистрация: 18.01.2021
Сообщений: 3,489
20.11.2022, 02:38
-_human_-, а дроби где?
0
78 / 73 / 19
Регистрация: 18.05.2021
Сообщений: 287
20.11.2022, 14:45
Я что-то дроби пропустил...
С дробями совсем другие пляски... Потребуется писать собственно свой калькулятор, для складывания, вычитания, сложения и умножения дробей, приводить к правильному виду... Но сам метод перевода строки в число можно оставить тот же. Просто добавить в ключи "пятых, вторых, тысячных" и т.д., немного переписав алгоритм. И воспринимать все целые числа как дробь n первых. Для удобства.
0
Эксперт Python
8849 / 4501 / 1864
Регистрация: 27.03.2020
Сообщений: 7,317
20.11.2022, 16:54
Вроде так:
Python
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
201
202
203
204
LIST_OP = [' плюс ', ' минус ', ' умножить ']
 
DICT_DIGIT_TO_STRING = {
    0: ('ноль',),
    1: ('один', 'одна', 'первых'),
    2: ('два', 'две', 'вторых'),
    3: ('три', 'третьих'),
    4: ('четыре', 'четвертых'),
    5: ('пять', 'пятых'),
    6: ('шесть', 'шестых'),
    7: ('семь', 'седьмых'),
    8: ('восемь', 'восьмых'),
    9: ('девять', 'девятых'),
    10: ('десять', 'десятых'),
    11: ('одиннадцать', 'одиннадцатых'),
    12: ('двенадцать', 'двенадцатых'),
    13: ('тринадцать', 'тринадцатых'),
    14: ('четырнадцать', 'четырнадцатых'),
    15: ('пятнадцать', 'пятнадцатых'),
    16: ('шестнадцать', 'шестнадцатых'),
    17: ('семнадцать', 'семнадцатых'),
    18: ('восемнадцать', 'восемнадцатых'),
    19: ('девятнадцать', 'девятнадцатых'),
    20: ('двадцать', 'двадцатых'),
    30: ('тридцать', 'тридцатых'),
    40: ('сорок', 'сороковых'),
    50: ('пятьдесят', 'пятидесятых'),
    60: ('шестьдесят', 'шестидесятых'),
    70: ('семьдесят', 'семидесятых'),
    80: ('восемьдесят', 'восьмидесятых'),
    90: ('девяносто', 'девяностых'),
    100: ('сто', 'сотых'),
    200: ('двести', 'двухсотых'),
    300: ('триста', 'трехсотых'),
    400: ('четыреста', 'четырехсотых'),
    500: ('пятьсот', 'пятисотых'),
    600: ('шестьсот', 'шестисотых'),
    700: ('семьсот', 'семисотых'),
    800: ('восемьсот', 'восьмисотых'),
    900: ('девятьсот', 'девятисотых'),
    1000: ('одна тысяча', 'тысячных'),
    2000: ('две тысячи', 'двухтысячных'),
    3000: ('три тысячи', 'трехтысячных'),
    4000: ('четыре тысячи', 'четырехтысячных'),
    5000: ('пять тысяч', 'пятитысячных'),
    6000: ('шесть тысяч', 'шеститысячных'),
    7000: ('семь тысяч', 'семитысячных'),
    8000: ('восемь тысяч', 'восьмитысячных'),
    9000: ('девять тысяч', 'девятитысячных')
}
DICT_STRING_TO_DIGIT = {v1: k for k, v in DiCT_DIGIT_TO_STRING.items() for v1 in v}
 
 
def proper_fraction(*args):
    def gcd_(x, y):
        while y:
            x, y = y, x % y
        return x 
        
    num, denom = args
    d = gcd_(num, denom)
    return num//d, denom//d 
 
 
def add_fractions(*args):
    a, b, c, d = args
    num = a*d + b*c 
    denom = d*b
    return proper_fraction(num, denom)
 
 
def diff_fractions(*args):
    a, b, c, d = args
    num = a*d - b*c 
    denom = d*b 
    return proper_fraction(num, denom)
 
 
def mult_fractions(*args):
    a, b, c, d = args
    num = a*c 
    denom = d*b 
    return proper_fraction(num, denom)
 
 
def args_split(stri):
    stri = (stri,)
    for key in LIST_OP:
        stri = stri[0].partition(key)
        if stri[2]:
            break
    else:
        stri = (stri[0], ' плюс ', 'ноль',)
    return stri
 
 
def string_to_digit(stri):
    def fractional(s):
        s = [DICT_STRING_TO_DIGIT[e] for e in s.split()]
        tmp = i = 0
        n = s[0]
        while i < len(s)-1:
            if s[i] > s[i+1]:
                n += s[i+1]
            else:
                tmp = n
                n = s[i+1]
            i += 1
        return tmp, n
        
    res = []
    stri = stri.replace('ья', 'ьих')\
                .replace('ая', 'ых')\
                .split(' и ')
    
    if stri[0].endswith('х'):
        return proper_fraction(*fractional(stri[0]))
        
    if len(stri) == 1:
        return proper_fraction(fractional(stri[0])[-1], 1)
        
    res = [fractional(stri[0])[-1], *fractional(stri[1])]
    return proper_fraction(res[0]*res[2] + res[1], res[2])
 
 
def digit_to_string(dig):
    k = 1000
    txt = []
    while k:
        if dig > k-1:
            if dig > 20:
                txt.append(DICT_DIGIT_TO_STRING[dig//k*k][0])
                dig %= k 
            else:
                txt.append(DICT_DIGIT_TO_STRING[dig][0])
                k = 0
        k //= 10
    return txt
 
 
def calc(st):
    args_text = args_split(st)
 
    args_1 = string_to_digit(args_text[0])
    args_2 = string_to_digit(args_text[2])
 
    if args_text[1] == ' плюс ':
        res = add_fractions(*args_1, *args_2)
    elif args_text[1] == ' минус ':
        res = diff_fractions(*args_1, *args_2)
    else:
        res = mult_fractions(*args_1, *args_2)
    
    if res[0] < 0:
        result = ['минус']
        res = (-res[0], res[1])
    elif res == 0:
        result = ['ноль']
    else:
        result = []
 
    num_, denom = res
    int_dig, num = divmod(num_, denom)
 
    if int_dig:
        result.extend(digit_to_string(int_dig) + ['и']*(num>0))
    if num>0:
        num_ = ['одна'] if num==1 else \
                ['две'] if num==2 else \
                digit_to_string(num)
        if num_[-1] == 'один':
            num_[-1] = 'одна'
        b = digit_to_string(denom)
    
        result += num_ + b
 
        result[-1] = DICT_DIGIT_TO_STRING[DICT_STRING_TO_DIGIT[result[-1]]][-1]
        if num == 1:
            result[-1] = result[-1].replace('ьих', 'ья')\
                        .replace('ых', 'ая')
    print(' '.join(result))
 
 
calc('двадцать три и три восьмых минус двадцать три и семь восьмых')
calc('двадцать три и три восьмых минус двадцать три и три восьмых')
calc('три плюс семьдесят пять')
calc('девяносто девять и девяносто семь девяносто девятых плюс девяносто семь и девяносто один девяносто седьмых')
calc('девяносто девять и девяносто семь девяносто девятых минус девяносто семь и девяносто один девяносто седьмых')
calc('девяносто девять и девяносто семь девяносто девятых умножить девяносто семь и девяносто один девяносто седьмых')
calc('три восьмых минус двадцать три и три восьмых')
calc('три восьмых минус двадцать три и одна восьмая')
calc('восемь')
 
"""
минус одна вторая
ноль
семьдесят восемь
сто девяносто семь и восемь тысяч восемьсот пятнадцать девять тысяч шестьсот третьих
два и четыреста девять тысяч шестьсот третьих
девять тысяч семьсот девяносто один и восемь тысяч двадцать семь девять тысяч шестьсот третьих
минус двадцать три
минус двадцать два и три четвертых
восемь
"""
2
Эксперт Python
 Аватар для Red white socks
4523 / 1899 / 336
Регистрация: 18.01.2021
Сообщений: 3,489
20.11.2022, 21:05
del
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
20.11.2022, 21:05
Помогаю со студенческими работами здесь

Текстовый калькулятор
Доброго времени суток. Мне было дано следующее задание: Сделайте текстовый калькулятор Пусть у вас есть число n, изначально 0 в цикле...

Текстовый калькулятор
Нужно написать текстовый калькулятор. Суть: вводится строка типа 2+4*(5-3)/8 и затем высчитывается ее значение. Еще нужно выполнить...

Текстовый калькулятор
Доброго времени суток! Идея такая: в Edit вводится строка, типа 3+5*(sqrt(4)-2,2)/3, нажимается кнопка, программа это считает и выводит...

Комментарии к листингу (калькулятор, текстовый редактор)
Напишите пожалуйста комментарии к строкам листинга.

Как преобразовать обычный калькулятор в калькулятор использующий класс стек?
#include &lt;iostream&gt; int main(){ int a = 0; int b = 0; char operation; std::cout &lt;&lt; &quot;Enter first number: &quot;; ...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru