Задача: Напишите простой калькулятор, который считывает с пользовательского ввода три строки: первое число, второе число и операцию, после чего применяет операцию к введённым числам («первое число» «операция» «второе число») и выводит результат на экран.
Поддерживаемые операции: +, -, /, *, mod, pow, div, где
mod — это взятие остатка от деления,
pow — возведение в степень,
div — целочисленное деление.
Проблема: При операциях с нулем возвращает:
Traceback (most recent call last):
File «jailed_code», line 9, in
print(n1 % n2)
ZeroDivisionError: float modulo
Мой код:
n1 = float(input())
n2 = float(input()
o = str(input())
if o == 'mod':
if (n1 or n2) == 0.0:
print("Деление на 0!")
else:
print(n1%n2)
elif o == 'div':
if (n1 or n2) == 0.0:
print("Деление на 0!")
else:
print(n1//n2)
elif o == '/':
if (n1 or n2) == 0.0:
print("Деление на 0!")
else:
print(n1/n2)
elif o == '*':
print(n1 * n2)
elif o == '+':
print(n1 + n2)
elif o == '-':
print(n1 - n2)
elif o == 'pow':
print(n1 ** n2)
else:
print('Something was wrong')
Замените условие на
if not b and ( c=='mod' or c=='/' or c=='div'):
print("Делеение на ноль")
или лучше на
if not b and c in ['/','%', 'mod', 'div']:
print("Делеение на ноль")
а так пара других вариантов
a = float(input())
b = float(input())
c = input()
z_div = 'Деление на ноль!"
OPERATORS = {
"+": a + b,
"-": a - b,
"*": a * b,
"/": a / b if b else z_div,
"mod": a % b if b else z_div,
"div": a // b if b else z_div,
"pow": a ** b
}
print(OPERATORS[c])
более понятный вариант, но придется вычислять все варианты.
Более python way :
a = float(input())
b = float(input())
c = input()
z_div = 'Деление на ноль!'
OPERATORS = {
"+": lambda x, y: x + y,
"-": lambda x, y: x - y,
"*": lambda x, y: x * y,
"/": lambda x, y: x / y if y else None,
"mod": lambda x, y: x % y if y else None,
"div": lambda x, y: x // y if y else None,
"pow": lambda x, y: x ** y
}
print(OPERATORS[c](a, b))
АНАЛог с eval :
a = input()
b = input()
c = input()
OPERATORS = {
"+": "+",
"-": "-",
"*": "*",
"/": "/",
"mod": "%",
"div": "//",
"pow": "**"
}
if not float(b) and c in ['/','%', 'mod', 'div']:
print('Деление на ноль!')
else:
print(
eval(
a + OPERATORS[c] + b
)
)
Ошибка:
1. File "<string>", line 568, in monstr_damage
2. ZeroDivisionError: float divmod()
data[f"self.id_user"]["hero"]["i"][1]
находится в радиусе от [0, 4]. Но чуть выше у меня стоит проверка на 0, он точно не попадает внутрь этой функции. Итог: от [1, 4]
Ошибка в этом кусочке кода:
crit = {"1": 0.09,"2":0.03,"3":0.5,"4":0.02}#566
if random.triangular(0,1) <= crit[f'{data[f"{self.id_user}"]["hero"]["i"][1]}']:#567
if crit[f'{data[f"{self.id_user}"]["hero"]["i"][1]}'] * 1.5 >= random.triangular(0,1):#568
damage_type = "критический-2"#569
damage_crit = random.triangular(1.15,1.45)#570
else:#571
damage_type = 'критический-1'#572
damage_crit = random.triangular(1.05,1.10)#573
else:#574
damage_type = "простой"#575
damage_crit = 0#576
Автор оригинала: Pankaj Kumar.
В этой статье мы раскрываем работу и использование функции Python divmod () в деталях.
1. Функция Python divmod ()
Python имеет встроенную функцию divmod (), которая выполняет разделение и модуль Работа на двух входных значениях.
divmod ()
Функция берет Две значения как аргументы и выполняет разделение I.e. value1/value2 и модуль операции т.е. Значение1% Value2 и Возвращает фактор и остаток как пара.
Синтаксис:
- Value1 рассматривается как номинатор
- Значение2 рассматривается как знаменатель
Пример 1:
x= 10 y= 2 res_div = divmod(x,y) print(res_div)
В приведенном выше примере мы прошли 10 и 2 на функцию divmod (). Кроме того, функция divmod () выполняет разделение I.e. 10/2 и модуль операции т.е. 10% 2 и возвращает кожи и остаток из него.
Выход:
Пример 2:
x= int(input()) y= int(input()) res_div = divmod(x,y) print(res_div)
Выход:
Пример 3:
x= 10 y= 3 res_div = divmod(x,y) print(res_div)
Выход:
Функция Python divmod () с значениями поплавка
Когда функционирует функцию divmod () поплавок ценности В качестве аргументов функция вычисляет фактор и остаток аналогичным образом, как показано выше.
Но когда значение поплавка передается как аргумент функции divmod (), это Возвращает фактическое значение, учитывая только всю часть значения получил то есть он пропускает десятичную часть.
Пример:
x= 10.5 y= 5 res_div = divmod(x,y) print(res_div)
Как видно выше, Divmod (10,5, 5) вернется (2.0, 0,5), потому что когда возникают значения поплавка, он пропускает десятичную часть в результате I.e. 10,5/5 будет 2,0 вместо 2.1. Таким образом, опуская десятичную часть.
Выход:
Пример 2:
x= 10 y= 2.4 res_div = divmod(x,y) print(res_div)
Выход:
(4.0, 0.40000000000000036)
Python divmod () Функциональные ошибки и исключения
1. Если значение Первый аргумент передается на функцию divmod () – ноль (0) Затем функция возвращает пару как (0, 0) Отказ
Пример 1:
x= 0 y= 3 res_div = divmod(x,y) print(res_div)
Выход:
2. Если значение Второй аргумент передается функцию divmod (), похоже, кажется ноль (0) Тогда функция возвращает ZerodivisionError I.E. Разделите на нулевую ошибку Отказ
Пример 2:
x= 5 y= 0 res_div = divmod(x,y) print(res_div)
Выход:
Traceback (most recent call last): File "main.py", line 4, in res_div = divmod(x,y) ZeroDivisionError: integer division or modulo by zero
3. Если функция divmod () встречает Комплексное число Как аргумент, он поднимает Типеррор исключение
Пример 3:
inp1 =10 + 5J inp2 = 4 res_div = divmod(inp1, inp2) print(res_div)
Выход:
Traceback (most recent call last): File "main.py", line 4, in res_div = divmod(inp1, inp2) TypeError: can't take floor or mod of complex number.
Резюме
- Функция Python divmod () принимает два значения в качестве списка параметров и выполняет разделение и модуль на двух значениях.
- Функция divmod () возвращает Quicent и остаток как пара.
- Если Поплавок ценить Передается на функцию divmod (), функция возвращает пару фактических и остальных от пропуская десятичную часть в соответствующих полученных значениях.
- А ZerodivisionError поднят, если Второй аргумент, переданный на функцию divmod (), равен нулю (0) Отказ
- Функция поднимает исключение в системе типа, если сложное число передается в качестве аргумента.
Заключение
Таким образом, в этой статье мы поняли работу функции Python Divmod ().
использованная литература
- Python divmod () – JouroneDev
krenddel 0 / 0 / 0 Регистрация: 25.04.2020 Сообщений: 14 |
||||
1 |
||||
26.04.2020, 12:21. Показов 12856. Ответов 2 Метки нет (Все метки)
В коде:
############################ Traceback (most recent call last): Хотя,там написано, что если b равно 0, то вывести «деление на ноль»
0 |
Programming Эксперт 94731 / 64177 / 26122 Регистрация: 12.04.2006 Сообщений: 116,782 |
26.04.2020, 12:21 |
2 |
25 / 9 / 0 Регистрация: 26.11.2018 Сообщений: 82 |
|
26.04.2020, 12:31 |
2 |
На 26 строке вы ставите в условие строку, а надо число. И на 19 замените, где проводится операция деления
0 |
Viktorrus 1728 / 967 / 199 Регистрация: 22.02.2018 Сообщений: 2,694 Записей в блоге: 6 |
||||||||
26.04.2020, 12:38 |
3 |
|||||||
b==’0′ Вы число сравниваете со строкой. Если b будет равно нулю, у Вас условие все равно будет False, то есть у Вас не определяется, когда b равно нулю. Исправте в условии на
0 |
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
26.04.2020, 12:38 |
3 |
Hello,
I am trying to learn how swapface is working. I tried to run the extraction script but I’ve got the following error : «ZeroDivisionError: float divmod()».
Do have you have an idea about this issue ?
Thanks a lot.
Details :
(venv) C:UsersDemaciiiiiiiiiiaAppDataLocalProgramsPythonPython37-32Libsite-packagesfaceswap-master>python faceswap.py extract -i ~/faceswap/photo/cage -o ~/faceswap/data/cage
Setting Faceswap backend to NVIDIA
10/31/2019 12:18:58 INFO Log level set to: INFO
10/31/2019 12:19:01 INFO Output Directory: C:UsersDemaciiiiiiiiiiafaceswapdatacage
10/31/2019 12:19:01 INFO Input Directory: C:UsersDemaciiiiiiiiiiafaceswapphotocage
10/31/2019 12:19:01 INFO Loading Detect from S3Fd plugin…
10/31/2019 12:19:01 INFO Loading Align from Fan plugin…
10/31/2019 12:19:01 INFO Loading Mask from Extended plugin…
10/31/2019 12:19:04 ERROR Got Exception on main handler:
Traceback (most recent call last):
File «C:UsersDemaciiiiiiiiiiaAppDataLocalProgramsPythonPython37-32Libsite-packagesfaceswap-masterlibcli.py», line 127, in execute_script
process = script(arguments)
File «C:UsersDemaciiiiiiiiiiaAppDataLocalProgramsPythonPython37-32Libsite-packagesfaceswap-masterscriptsextract.py», line 42, in init
normalize_method=normalization)
File «C:UsersDemaciiiiiiiiiiaAppDataLocalProgramsPythonPython37-32Libsite-packagesfaceswap-masterpluginsextractpipeline.py», line 79, in init
self._set_extractor_batchsize()
File «C:UsersDemaciiiiiiiiiiaAppDataLocalProgramsPythonPython37-32Libsite-packagesfaceswap-masterpluginsextractpipeline.py», line 449, in set_extractor_batchsize
self.set_plugin_batchsize(plugin, available_vram)
File «C:UsersDemaciiiiiiiiiiaAppDataLocalProgramsPythonPython37-32Libsite-packagesfaceswap-masterpluginsextractpipeline.py», line 465, in _set_plugin_batchsize
plugin.batchsize = int(max(1, available_vram // plugin.vram_per_batch))
ZeroDivisionError: float divmod()
10/31/2019 12:19:05 CRITICAL An unexpected crash has occurred. Crash report written to ‘C:UsersDemaciiiiiiiiiiaAppDataLocalProgramsPythonPython37-32Libsite-packagesfaceswap-mastercrash_report.2019.10.31.121904994675.log’. You MUST provide this file if seeking assistance. Please verify you are running the latest version of faceswap before reporting
October 22, 2019
Floor Division in Python
- The Problem
- Avoiding this Error
- Definition of Floor Division
- Python Arithmetic
- float_floor_div
- float_divmod
- Division by Zero
- Quotient and Dividend
- Remainder Sign
- Remainder is Zero
- Calling Floor
- Numerator is Zero
- Returning the Tuple
- Design Decisions
- PEP 328
- PEP 3141
- Further Debate
- Conclusions
- Breaking Changes
- Simplicity
- Speed
- Polymorphism
The Problem
In solving data analytics problems, occasionally we must bin data into intervals or categories based on some arbitrary stratification. A common example outside of the world of computer science is letter grades, a concept that can be abstracted1 to:
def grade(score):
grades = ['F', 'D', 'C', 'B', 'A']
if score >= 100:
return 'A'
if score <= 50:
return 'F'
return grades[(score - 50) // 10]
Thus, for:
scores = [88, 72, 61, 39, 97]
results = [grade(score) for score in scores]
We get:
['B', 'C', 'D', 'F', 'A']
However, if any of our score
values2 are not integers we will encounter a TypeError
:
>>> grade(61.2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
TypeError: list indices must be integers or slices, not float
This is caused by the following type coercion, as lists cannot be indexed by floats:
>>> (61.2 - 50) // 2
1.0
Avoiding this Error
Of course, we can cast to an int:
def grade(score):
grades = ['F', 'D', 'C', 'B', 'A']
if score > 99:
return 'A'
if score <= 50:
return 'F'
return grades[(int(score) - 50) // 10]
However, for large datasets this is not an efficient operation:
chris% python -m timeit 'int(102.3 // 2)'
5000000 loops, best of 5: 99.6 nsec per loop
chris% python -m timeit '102.3 // 2'
50000000 loops, best of 5: 7.05 nsec per loop
In my real-world example, the score
equivalent is always a float, so we can map the float integer values to their respective categories3, similar to:
>>> grades
{0.0: 'F', 1.0: 'D', ...}
>>> grades[0]
'F'
>>> grades[0.]
'F'
>>> grades[1]
'D'
>>> grades[1.]
'D'
However, I was still curious why floor division was returning a float and not an integer.
Definition of Floor Division
According to Concrete Mathematics4:
⌊x⌋ = the greatest integer less than or equal to x
⌈x⌉ = the least integer greater than or equal to x
Note the key word integer; while this may be the official mathematical definition, Python does not seem to follow this to the letter and returns a type-coerced value.
Python Arithmetic
It is documented when types are coerced. From the Python docs:
- If either argument is a complex number, the other is converted to complex;
- otherwise, if either argument is a floating point number, the other is converted to floating point;
- otherwise, both must be integers and no conversion is necessary.
The same is true for binary operators:
The / (division) and // (floor division) operators yield the quotient of their arguments. The numeric arguments are first converted to a common type. Division of integers yields a float, while floor division of integers results in an integer; the result is that of mathematical division with the ‘floor’ function applied to the result.
float_floor_div
The float divmod
work occurs in float_floor_div
, which comes from the cpython source. All this function does is call float_divmod
and dereferences the quotient:
static PyObject *
float_floor_div(PyObject *v, PyObject *w)
{
PyObject *t, *r;
t = float_divmod(v, w);
if (t == NULL || t == Py_NotImplemented)
return t;
assert(PyTuple_CheckExact(t));
r = PyTuple_GET_ITEM(t, 0);
Py_INCREF(r);
Py_DECREF(t);
return r;
}
The bulk of the work occurs inside of the called function, float_divmod
.
float_divmod
The source for float_divmod
lives here. The first step of this function handles the type cast:
float_divmod(PyObject *v, PyObject *w)
{
double vx, wx;
double div, mod, floordiv;
CONVERT_TO_DOUBLE(v, vx);
CONVERT_TO_DOUBLE(w, wx);
...
Where vx
is the dividend, and wx
is the divisor. The rest of this function handles the various cases that can occur:
Division by Zero
If the divisor is zero, we raise an error:
...
if (wx == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, "float divmod()");
return NULL;
}
...
Quotient and Dividend
Before we can do any work, we must calculate the quotient and dividend:
mod = fmod(vx, wx);
div = (vx - mod) / wx;
We get the modulus using the fmod
function from the C Standard Library, and the quotient using float division, also leveraging the C standard library.
Remainder Sign
Once we have these values, we check to ensure the sign is correct.
...
if (mod) {
if ((wx < 0) != (mod < 0)) {
mod += wx;
div -= 1.0;
}
}
...
Remainder is Zero
If the remainder (i.e., the modulus) is zero, we copy the sign to the divisor with copysign(0.0, wx)
5.
Calling Floor
If the quotient is not zero, we call the floor
function:
...
if (div) {
floordiv = floor(div);
if (div - floordiv > 0.5)
floordiv += 1.0;
}
...
Numerator is Zero
If the dividend is zero, we copy the sign of the quotient onto zero with copysign(0.0, vx / wx)
.
Returning the Tuple
Once all of this has completed, we return a tuple like (floor_qotient, modulus)
.
Design Decisions
As Python is a mature language, the changes that affected these behaviors underwent much debate.
PEP 328
Since the proposal of the Python 3 change to the division operator in PEP 238, it was decided that the result of floor division with floats would be a float, following the above arithmetic conversions:
In particular, if a and b are both ints or longs, the result has the same type and value as for classic division on these types (including the case of mixed input types;
int // long
andlong // int
will both return a long).For floating point inputs, the result is a float. For example:
3.5 // 2.0 == 1.0
PEP 3141
This PEP defined the changes to the numerical stack in Python and explicitly noted the following:
__floor__(self)
, called frommath.floor(x)
, which returns the greatestIntegral <= x
.
Thus, it would follow that the floor
call in float_divmod
should return an integer and not a float value. However, this is not the case.
Further Debate
Thirteen years later, Alexander Belopolsky reported Issue 22444: Floor divide should return int:
PEP 3141 defines floor division as
floor(x/y)
and specifies thatfloor()
should return int type. Builtin float type has been made part of the PEP 3141 numerical tower, but floor division of two floats still results in a float.
In this thread, my exact issue accessing a list index above was raised:
This is one of the common uses of floor division — to find an index of a cell in a regular grid:
(x - start) // step
. In this situation, it is convenient to have the result ready to be used as an index without a cast.
However, the decision to not make this change ended with Raymond Hettinger’s reply:
-
The current behavior has been around for a long time and is implemented in several modules, including
decimal
andfraction
. As core devs, we need to keep focused on a priority of making the language stable (not making changes that truly necessary and invalidating all previously published material) and more importantly not adding yet more obstacles to converting from Python 2 to Python 3 (which Guido has called «death by a thousand cuts»). -
The current behavior can be useful it that it allows floor division operations without unexpected type conversions occurring in the middle of an expression. We really don’t want to break those use cases.
Conclusions
Python’s philosophy means the language provides high-level access to data structures. Here, the coercion avoids dealing with the nuances of numeric types that one would have to wrangle with when writing C. In C, given the different numerical types, you have to return a double, because the range of a double is so much larger than that of an integer.
Breaking Changes
These decisions were made during the early days of the Python 3 transition, where the core developers wanted to minimize the friction of the upgrade from 2 to 3. As a result, to not break code that depended on floor division being type preserving6, it was decided that floor division should return a value equal to an integer7 but agnostic of type.
In a post-Python 2 era, these concerns do not hold the same weight. This is an example of some technical debt that Python has accrued, as other parts of Python do not behave this way:
>>> type(timedelta(2.2) // timedelta(3))
<class 'int'>
>>> type(Fraction(2.3) // Fraction(1))
<class 'int'>
Simplicity
Python makes sacrifices to retain its beauty and simplicity, this being one of them. As a result, the programmer, in this instance, is unable to choose the functionality that best addresses a specific problem. A possible solution would be to provide both floor()
and float_floor()
for accessing these values in both types. Also possible would be to make lists accessible by the float counterparts of their integer indices, since 1 == 1.0
.
Speed
Further, the language is far more performant as a result of this decision: float // any == float
is a computationally simple and fast operation; float // any == int
is significantly more complicated and expensive, especially for large inputs due to the inefficient cast from float back to int.
chris% python -m timeit 'int(102.3 // 2)'
5000000 loops, best of 5: 99.6 nsec per loop
chris% python -m timeit '102.3 // 2'
50000000 loops, best of 5: 7.05 nsec per loop
This performance hit does not stem from the float conversion itself 8 but rather from the fact that integer and float values are stored in different registers: the CPU must first store the float from the FPU register in memory, then read that memory address into the int register. This is a classic example of a load-hit-store stall.
Polymorphism
Since we can combine types in this way in Python, we need to be cognizant of the pitfalls that we can run into when writing polymorphic functions. Most of the time, the type of number will not matter to the Python interpreter. When type does matter, understanding how these data are handled internally leads to a smoother development process.
Discussion: Hacker News, Reddit
a = input() f = float(a.replace(',','.')) b = float(input()) c = input() if b == 0 and (c == 'div' or 'mod' or '/'): print('Деление на 0!') elif c == '+': print(f + b) elif c == '-': print(f - b) elif c == '*': print(f * b) elif c == '/': print(f / b) elif c == 'mod': print(f % b) elif c == 'div': print(f // b) elif c == 'pow': print(f ** b)
При вводных данных:
5
0
— или +
Выводит “Деление на 0!”
При
if b == 0 and (c == 'div' or 'mod' or '/') and not(c == '-' or '+')
Вот такая штука с mod
Test input: 5.0 0.0 mod Correct output: Деление на 0! Your code output: Error: Traceback (most recent call last): File "jailed_code", line 16, in <module> print(f % b) ZeroDivisionError: float modulo
И вот такая с div
Traceback (most recent call last): File "jailed_code", line 18, in <module> print(f // b) ZeroDivisionError: float divmod()
Само задание для написание калькулятора:
Напишите простой калькулятор, который считывает с пользовательского ввода три строки: первое число, второе число и операцию, после чего применяет операцию к введённым числам (“первое число” “операция” “второе число”) и выводит результат на экран.
Поддерживаемые операции: +, -, /, *, mod, pow, div, где
mod — это взятие остатка от деления,
pow — возведение в степень,
div — целочисленное деление.
Если выполняется деление и второе число равно 0, необходимо выводить строку “Деление на 0!”.
Обратите внимание, что на вход программе приходят вещественные числа.