Форум программистов, компьютерный форум, киберфорум
Python для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.93/55: Рейтинг темы: голосов - 55, средняя оценка - 4.93
1 / 1 / 1
Регистрация: 19.10.2020
Сообщений: 17

Калькулятор дробей

19.10.2020, 11:35. Показов 11660. Ответов 7

Студворк — интернет-сервис помощи студентам
Это калькулятор дробей можно вводить -,+,/,*.
Но с минусом есть проблемы, если написать уравнение "-1--2" или "1--2", или "-1-2", то программа будет разделять элементы по минусу(вместо [-1, 2], будет ["", 1, 2], если использовать уравнение "1--2"), как можно исправить этот баг?

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
def fraction_reduction(fraction, minus1, minus2):
  """fraction_reduction text"""
 
  while fraction[0] % 2 == 0 and fraction[1] % 2 == 0:
    fraction = [fraction[0] // 2, fraction[1] // 2]
 
  divisor = 3
  while divisor <= fraction[0] and divisor <= fraction[1]:
    while fraction[0] % divisor == 0 and fraction[1] % divisor == 0:
      fraction = [fraction[0] // divisor, fraction[1] // divisor]
      divisor += 2
 
  integer = 0
  if fraction[0] >= fraction[1]:
    integer = fraction[0] // fraction[1]
 
    for _ in range(int(integer)):
      fraction[0] = fraction[0] - fraction[1]
  fraction = [fraction[0], fraction[1]]
  print_fraction(integer, fraction, minus1, minus2)
 
 
def string_to_fraction(string):    
 
  string = string.replace(' ', '')
  string1 = string[1::]
 
  actions = ["*", "\\", "+", "-"]
 
  for action in actions:
    ind_actions = string1.find(action)      #вот тут этот баг, если не ошибаюсь
    ind_actions += 1
 
    if ind_actions != 0:
      break
 
  string_list = string.split(string[ind_actions])
  fraction1_str = string_list[0]
  action = string[ind_actions]
  fraction2_str = string_list[1]
 
  if fraction1_str.find("/") != -1:
    fraction1 = [int(i) for i in fraction1_str.split("/")]
  else:
    fraction1 = [int(fraction1_str), 1]
 
  if fraction2_str.find("/") != -1:
    fraction2 = [int(i) for i in fraction2_str.split("/")]
  else:
    fraction2 = [int(fraction2_str), 1]
 
  fraction_minus1 = str(fraction1).find("-")
  fraction_minus2 = str(fraction2).find("-")
 
  if fraction_minus1 == 1:
    minus1 = 1
    fraction1[0] = abs(int(fraction1[0]))
 
  else:
    minus1 = 0
  if fraction_minus2 == 1:
    minus2 = 1
    fraction2[0] = abs(int(fraction2[0]))
  else:
    minus2 = 0
 
  return fraction1, action, fraction2, minus1, minus2
 
 
def fraction_actions(fraction1, action, fraction2, minus1, minus2):
  
  if action == "*":
    numerator = fraction1[0] * fraction2[0]
    denumerator = fraction1[1] * fraction2[1]
    if minus1 == 1 and minus2 == 1 :
      minus1, minus2 = 0, 0
 
  elif action == '\\':
    numerator = fraction1[0] * fraction2[1]
    denumerator = fraction1[1] * fraction2[0]
    if minus1 == 1 and minus2 == 1 :
      minus1, minus2 = 0, 0
 
  elif action == '+':
    if minus1 != 1 and minus2 != 1:
      numerator = fraction1[0] * fraction2[1] + fraction2[0] * fraction1[1]
      denumerator = fraction1[1] * fraction2[1]
 
  elif minus1 == 1 and minus2 == 0:
    numerator = fraction1[0] * fraction2[1] - fraction2[0] * fraction1[1]
    denumerator = fraction1[1] * fraction2[1]
    if fraction1 < fraction2:
      minus1 = 0
    else:
      minus1 = 1
  elif minus1 == 0 and minus2 == 1:
    numerator = fraction1[0] * fraction2[1] - fraction2[0] * fraction1[1]
    denumerator = fraction1[1] * fraction2[1]
    if fraction1 > fraction2:
      minus1 = 0
      minus2 = 0
    else:
      minus2 = 1
  elif minus1 == 1 and minus2 == 1:
    numerator = fraction1[0] * fraction2[1] + fraction2[0] * fraction1[1]
    denumerator = fraction1[1] * fraction2[1]
    if fraction2 > fraction1:
      minus1 = 1
 
  elif action == '-':
    if minus1 != 1 and minus2 != 1:
      numerator = fraction1[0] * fraction2[1] - fraction2[0] * fraction1[1]
      denumerator = fraction1[1] * fraction2[1]
      if fraction1 < fraction2:
        minus1 = 1
    elif minus1 == 1 and minus2 != 1:
      numerator = fraction1[0] * fraction2[1] + fraction2[0] * fraction1[1]
      denumerator = fraction1[1] * fraction2[2]
      minus1 = 1
    elif minus2 == 1 and minus1 == 0:
      numerator = fraction1[0] * fraction2[1] + fraction2[ 0] * fraction1[1]
      denumerator = fraction1[1] * fraction2[1]
      minus1 = 0
    elif minus1 == 1 and minus2 == 1:
      numerator = fraction2[0] * fraction1[1] - fraction1[0] * fraction2[1]
      if fraction1 < fraction2:
        minus1 = 0
      else:
        minus1 = 1
 
  fraction = [abs(numerator), abs(denumerator)]
  fraction_reduction(fraction, minus1, minus2)
 
 
def print_fraction(integer, fraction, minus1, minus2):
    print("Ответ:")
    if integer == 0 and fraction[0] == 1 and fraction[1] == 1:
 
        print(0)
        print("Введите следующий пример:")
    else:
        if minus1 == 1 or minus2 == 1:
 
            if fraction[1] == 1:
                integer += fraction[0]
 
            if fraction[0] and fraction[1] == 1 or fraction[0] == 0:
                print("-", integer, sep="")
                print("Введите следующий пример:")
 
            elif integer == 0 and fraction[0] != 0:
                print("-", fraction[0], "/", fraction[1], sep="")
                print("Введите следующий пример:", )
 
            elif integer != 0:
                print("-", integer, " ", fraction[0], "/", fraction[1], sep="")
                print("Введите следующий пример:")
 
        elif minus1 == 0 and minus2 == 0:
 
            if fraction[1] == 1:
                integer += fraction[0]
 
            if fraction[0] and fraction[1] == 1 or fraction[0] == 0:
                print(integer)
                print("Введите следующий пример:")
 
            elif integer == 0 and fraction[0] != 0:
                print(fraction[0], "/", fraction[1], sep="")
                print("Введите следующий пример:")
 
            elif integer != 0:
                print(integer, " ", fraction[0], "/", fraction[1], sep="")
                print("Введите следующий пример:")
 
 
def main():
    fraction1, action, fraction2, minus1, minus2 = string_to_fraction(input())
 
    fraction_actions(fraction1, action, fraction2, minus1, minus2)
 
 
print("Введите пример:")
 
if __name__ == "__main__":
    while True:
        main()
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
19.10.2020, 11:35
Ответы с готовыми решениями:

Калькулятор для обыкновенных дробей
Вводится одна дробь в виде: 2/7 (пример), и аналогично вторая Нужно убрать ‘/‘ и работать отдельно с a - числитель первой, b - ее...

Написать калькулятор обычных дробей
Дроби -обычные, то есть (числитель/знаменатель). Операции простые (+ - * /) Максимально просто, только учусь) Спасибо за внимание!

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

7
34 / 34 / 37
Регистрация: 21.06.2012
Сообщений: 152
20.10.2020, 23:04
Если вы решили учить и использовать питон, то пишите код исходя что это питон, а не C++.
Используйте тот факт что это интепритируемый язык, что позволяет вам генерировать и выполнять код питона в ходе выполнения программы (через eval).

Учитывая все это вам нужно всего лишь распарсить входное выражение на оператор и члены и проверить его на корректность, делается это через RegExp таким образом:
Code
1
^\s*(?P<first>-?\d+)\s*(?P<operator>[+\-*/])\s*(?P<second>-?\d+)\s*$
После чего проверяйте какой оператор, если деление выводите натуральную дробь (что бы записать долю используйте модуль fractions.Fraction), в иных случаях просто сгенерируйте python-код этого выражения и вычеслите его.

Выглядет это как-то так
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
import re
from fractions import Fraction
 
 
if __name__ == '__main__':
    prompt = "Введите пример:"
    while True:
        # Парсим входную строку, \s* устраняет лишние пробелы
        match = re.match(r"^\s*(?P<first>-?\d+)\s*(?P<operator>[+\-*/])\s*(?P<second>-?\d+)\s*$", input(prompt))
        if not match:
            raise ValueError("Некорректное выражение")
        action = match.group("operator")
        # Если деление то расписываем его результат через натуральную дробь
        if match.group("operator") == r"/":
            # Записываем дробную часть через юникодывые спецсимволы
            sup = "⁰¹²³⁴⁵⁶⁷⁸⁹"
            sub = "₀₁₂₃₄₅₆₇₈₉"
            first, second = map(int, match.group("first", "second"))
            div, mod = divmod(first, second)
            fraction = Fraction(mod, second)
            print(*filter(None, (div, "⁄".join((sup[fraction.numerator], sub[fraction.denominator])))))
        # В иных случаях просто оформляем как код python и выполняеем
        else:
            print(eval(action.join(match.group("first", "second"))))
        prompt = "Введите следующий пример:"
Если вы хотите все таки сделать через парсинг выражения и выполение его через отдельные фунции для каждого оператора в C++ стиле, то попробуйте заменить парсинг выражение в функции string_to_fraction на RegExp которые был выше.

Добавлено через 13 минут
Упустил момент с отрицательными числами в делении, этот код верный
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
import re
from fractions import Fraction
 
 
if __name__ == '__main__':
 
    prompt = "Введите пример:"
    while True:
        # Парсим входную строку, \s* устраняет лишнии пробелы
        match = re.match(r"^\s*(?P<first>-?\d+)\s*(?P<operator>[+\-*/])\s*(?P<second>-?\d+)\s*$", input(prompt))
        if not match:
            raise ValueError("Некорректное выражение")
        action = match.group("operator")
        # Если деление то расписываем его результат через натуральную дробь
        if match.group("operator") == r"/":
            # Записываем дробную часть через юникодывые спецсимволы
            sup = "⁰¹²³⁴⁵⁶⁷⁸⁹"
            sub = "₀₁₂₃₄₅₆₇₈₉"
            first, second = map(int, match.group("first", "second"))
            div, mod = divmod(abs(first), abs(second))
            fraction = Fraction(mod, abs(second))
            minus = "-" if (first < 0) != (second < 0) else None
            print(*filter(None, (minus, div, "⁄".join((sup[fraction.numerator], sub[fraction.denominator])))), sep="")
        # В иных случаях просто оформляем как код python и выполняеем
        else:
            print(eval(action.join(match.group("first", "second"))))
        prompt = "Введите следующий пример:"
Добавлено через 7 минут
Вот теперь все правильно, упустил что числители или знаменатели могут быть больше 9
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
import re
from fractions import Fraction
 
 
if __name__ == '__main__':
 
    prompt = "Введите пример:"
    while True:
        # Парсим входную строку, \s* устраняет лишнии пробелы
        match = re.match(r"^\s*(?P<first>-?\d+)\s*(?P<operator>[+\-*/])\s*(?P<second>-?\d+)\s*$", input(prompt))
        if not match:
            raise ValueError("Некорректное выражение")
        action = match.group("operator")
        # Если деление то расписываем его результат через натуральную дробь
        if match.group("operator") == r"/":
            def int2str(number: int, numbers: str) -> str:
                result = []
                while number:
                    result.append(numbers[number % 10])
                    number //= 10
                return "".join(reversed(result))
            # Записываем дробную часть через юникодывые спецсимволы
            sup = "⁰¹²³⁴⁵⁶⁷⁸⁹"
            sub = "₀₁₂₃₄₅₆₇₈₉"
            first, second = map(int, match.group("first", "second"))
            div, mod = divmod(abs(first), abs(second))
            fraction = Fraction(mod, abs(second))
            minus = "-" if (first < 0) != (second < 0) else None
            print(*filter(None, (minus, div, "⁄".join((int2str(fraction.numerator, sup), int2str(fraction.denominator, sub))))), sep="")
        # В иных случаях просто оформляем как код python и выполняеем
        else:
            print(eval(action.join(match.group("first", "second"))))
        prompt = "Введите следующий пример:"
0
Просто Лис
Эксперт Python
 Аватар для Рыжий Лис
5973 / 3735 / 1099
Регистрация: 17.05.2012
Сообщений: 10,791
Записей в блоге: 9
21.10.2020, 05:24
Ну это уже парсер писать надо...
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
TOKEN_MINUS = 0
TOKEN_NUMBER = 1
TOKEN_OP = 3
 
def tokenize(text):
    result = []
    buf = []
    for i in text:
        if i.isdigit():
            buf.append(i)
            continue
        elif buf:
            result.append((TOKEN_NUMBER, ''.join(buf)))
            buf = []
        if i == '-':
            result.append((TOKEN_MINUS, '-'))
            continue
        if i in '/*+':
            result.append((TOKEN_OP, '-'))
            continue
        raise ValueError(i)
    if buf:
        result.append((TOKEN_NUMBER, ''.join(buf)))
    return result
 
 
def f(text):
    tokens = tokenize(text)
    print(tokens)
    num1, op, num2 = None, None, None
    i = 0
    
 
f("-123--245")
f("1*-2")
f("-1-2")
Блин, регуляркой проще распарсить в данном случае...
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import re
 
def f(text):
    m1, n1, op, m2, n2 = re.findall(r'^(-?)(\d+)([-*+/])(-?)(\d+)$', text)[0]
    num1 = int(m1 + n1)
    num2 = int(m2 + n2)
    r = None
    if op == '-':
        r = num1 - num2
    print(num1, op, num2, '=', r)
 
f("-123--245")
f("1*-2")
f("-1-2")
Добавлено через 22 секунды
Code
1
2
3
-123 - -245 = 122
1 * -2 = None
-1 - 2 = -3
Добавлено через 2 минуты
Ещё проще
Python
1
2
3
    n1, op, n2 = re.findall(r'^(-?\d+)([-*+/])(-?\d+)$', text)[0]
    num1 = int(n1)
    num2 = int(n2)
0
Супер-модератор
Эксперт функциональных языков программированияЭксперт Python
 Аватар для Catstail
38195 / 21128 / 4309
Регистрация: 12.02.2012
Сообщений: 34,733
Записей в блоге: 14
21.10.2020, 09:21
Цитата Сообщение от creative16 Посмотреть сообщение
если написать уравнение "-1--2"
- это не уравнение... А по сути, ни один нормальный человек не будет (не должен) писать такую глупость, как "2--1". В С/C++/Java и многих других языках это вызывает ошибку.
Поэтому подобное лучше просто запретить.
0
Просто Лис
Эксперт Python
 Аватар для Рыжий Лис
5973 / 3735 / 1099
Регистрация: 17.05.2012
Сообщений: 10,791
Записей в блоге: 9
21.10.2020, 09:29
Цитата Сообщение от Catstail Посмотреть сообщение
писать такую глупость, как "2--1
Нормально это парсится. Первое - это минус. Второй - унарный минус. Питон, по крайней мере, понимает.
Python
1
2
>>> 2--1    
3
Но в питоне нет операторов инкремента и второй-как-его-зовут.
0
Супер-модератор
Эксперт функциональных языков программированияЭксперт Python
 Аватар для Catstail
38195 / 21128 / 4309
Регистрация: 12.02.2012
Сообщений: 34,733
Записей в блоге: 14
21.10.2020, 09:37
Цитата Сообщение от Рыжий Лис Посмотреть сообщение
Питон, по крайней мере, понимает.
- да программу можно заставить "понимать" что угодно. Питон и вот это:

Python
1
x=3----6
"понимает"... Но такой код свидетельствует о когнитивных проблемах у программиста.

Добавлено через 1 минуту
А если хочется использовать унарный минус - пожалуйста:

Python
1
x=4-(-y)  # тоже с "душком", но лучше чем 4--y
0
21.10.2020, 09:52

Не по теме:

Цитата Сообщение от Catstail Посмотреть сообщение
x=3----6
Я видел похожий пример на с++. Что-то типа такого:
C++
1
int result = x+++++y;
На мой неловкий комментарий, что это скорее всего не скомпилируется, так как нет символов-разделителей, мне вытащили документацию по с++ и продемонстрировали как именно компилятор с++ должен распарсить такую строку...

0
Супер-модератор
Эксперт функциональных языков программированияЭксперт Python
 Аватар для Catstail
38195 / 21128 / 4309
Регистрация: 12.02.2012
Сообщений: 34,733
Записей в блоге: 14
21.10.2020, 10:33
Рыжий Лис, да, на тестах при приеме на работу молодые (и считающие себя умными) обожают задавать вопросы типа: Пусть x=5. Чему будет равно значение переменной х после выполнения такого кода:

C++
1
  x=++x+x++;
Я бы даже не стал отвечать на такую глупость...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
21.10.2020, 10:33
Помогаю со студенческими работами здесь

Округление дробей
Надо написать два метода класса Fraction. методы округления в большую и меньшую сторону. у меня они пока работают не правильно ...

Вычитание дробей
На вход подается 4 числа: числитель и знаменатель первой дроби, затем числитель и знаменатель второй дроби.Выводится строка: числитель...

Сложение дробей в цикла
Я вот пытался решить задачу, но что то не то total=0.0 for numerator in range(1,30,1): for denominator in range(30,1,-1): ...

Класс рациональных дробей
Спасибо, что зашли) Задали нам написать класс рациональных дробей, толком ничего не объяснив. Должно быть реализовано: арифметические...

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


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

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
Вывод данных в справочнике через динамический список
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Функция заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
10 пpимет, которые всегда сбываются
Maks 31.03.2026
1. Чтобы, наконец, пришла маршрутка, надо закурить. Если сигарета последняя, маршрутка придет еще до второй затяжки даже вопреки расписанию. 2. Нaдоели зима и снег? Не надо переезжать. Достаточно. . .
Перемещение выделенных строк ТЧ из одного документа в другой
Maks 31.03.2026
Реализация из решения ниже выполнена на примере нетипового документа "ВыдачаОборудованияНаСпецтехнику" с единственной табличной частью "ОборудованиеИКомплектующие" разработанного в конфигурации КА2. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru