Отделение Python


133

Я пытался нормализовать набор чисел от -100 до 0 в диапазоне от 10 до 100, и у меня возникли проблемы только для того, чтобы заметить, что даже без каких-либо переменных это не оценивает то, как я ожидал:

>>> (20-10) / (100-10)
0

Деление с плавающей запятой тоже не работает:

>>> float((20-10) / (100-10))
0.0

Если любую сторону деления перевести в поплавок, это сработает:

>>> (20-10) / float((100-10))
0.1111111111111111

Каждая сторона в первом примере оценивается как int, что означает, что окончательный ответ будет приведен к int. Поскольку 0,111 меньше 0,5, оно округляется до 0. На мой взгляд, это непрозрачно, но я думаю, что так оно и есть.

Какое объяснение?



3
Адам, мне все еще не нравится ваше объяснение. Первый пример - целочисленное деление, которое просто возвращает 0. Второй пример заключен в круглые скобки для желаемого эффекта.
Президент Джеймс К. Полк

@GregS Проблема была в первом примере. Второй пример носит пояснительный характер и был написан после первого вопроса. Все ответы ниже очень хорошо объясняют проблему, особенно @KennyTM. Важно отметить, что моя исходная проблема связана только с Python 2.x, а не с 3. Немного обескураживает то, что поведение изменится таким образом, но теперь, когда я знаю, я буду использовать из будущего разделения импорта и использовать 3 .x поведение. Приветствия.
Адам Нельсон

1
Адам, пожалуйста, исправьте последнее РЕДАКТИРОВАНИЕ. Правая сторона не имеет ничего особенного; чтобы деление было плавающим, либо числитель, либо знаменатель (или оба) должны быть плавающими. Если вы думаете, что прочитали в документации, что правая часть должна быть плавающей, то либо документация сформулирована неправильно и ее следует исправить, либо вы ее неправильно поняли. Возможно, вы видели пример, а затем экстраполировали из него правило?
tzot

Ответы:


246

Вы используете Python 2.x, в котором целочисленные деления будут усекаться, а не превращаться в число с плавающей запятой.

>>> 1 / 2
0

Вы должны сделать один из них float:

>>> float(10 - 20) / (100 - 10)
-0.1111111111111111

или from __future__ import division, что заставляет /принять поведение Python 3.x, которое всегда возвращает число с плавающей запятой.

>>> from __future__ import division
>>> (10 - 20) / (100 - 10)
-0.1111111111111111

10
Если вы используете, from __future__ import divisionвы можете получить старое поведение деления в стиле C, используя две косые черты (например 1 // 2, приведет к 0). См. Pep 238. Изменение оператора деления
пользователь

1
@User Нет необходимости в импорте из __future__. В обоих Python 2 и 3 //относится к __floordiv__()по умолчанию.
Казимир

21

Вы вводите целые числа, поэтому Python возвращает вам целое число :

>>> 10 / 90
0

Если после этого преобразовать это значение в число с плавающей запятой, округление уже будет выполнено, другими словами, целое число 0 всегда будет равно 0 с плавающей точкой.

Если вы используете числа с плавающей запятой по обе стороны от деления, Python даст вам ожидаемый ответ.

>>> 10 / 90.0
0.1111111111111111

Итак, в вашем случае:

>>> float(20-10) / (100-10)
0.1111111111111111
>>> (20-10) / float(100-10)
0.1111111111111111

11

Вам нужно изменить его на float ДО того, как вы сделаете деление. То есть:

float(20 - 10) / (100 - 10)

4
@ Адам Нельсон: У меня работает правильно. Проверьте свои скобки.
Fred Larson

На самом деле, я ошибаюсь - но, посмотрев документацию, нужно сначала отбросить правую сторону.
Адам Нельсон

10
@ Адам: Неважно, с какой стороны первой.
kennytm 02

11

В Python 2.7 /оператор представляет собой целочисленное деление, если входные данные являются целыми числами:

>>>20/15
1

>>>20.0/15.0
1.33333333333

>>>20.0/15
1.33333333333

В Python 3.3 /оператор является делением с плавающей запятой, даже если входные данные являются целыми числами.

>>> 20/15
1.33333333333

>>>20.0/15
1.33333333333

Для целочисленного деления в Python 3 мы будем использовать //оператор.

//Оператор является оператором целочисленного деления как в Python 2.7 и Python 3.3.

В Python 2.7 и Python 3.3:

>>>20//15
1

Теперь посмотрите сравнение

>>>a = 7.0/4.0
>>>b = 7/4
>>>print a == b

Для вышеприведенной программы вывод будет False в Python 2.7 и True в Python 3.3.

В Python 2.7 a = 1,75 и b = 1.

В Python 3.3 a = 1,75 и b = 1,75 просто потому, что /это деление с плавающей запятой.


8

Это связано с используемой вами версией python. В основном он принимает поведение C: если вы разделите два целых числа, результаты будут округлены до целого. Также имейте в виду, что Python выполняет операции слева направо, что играет роль при приведении типов.

Пример: поскольку этот вопрос всегда возникает у меня в голове, когда я выполняю арифметические операции (нужно ли преобразовать в число с плавающей запятой и какое число), представлен пример из этого аспекта:

>>> a = 1/2/3/4/5/4/3
>>> a
0

Когда мы делим целые числа, неудивительно, что оно округляется ниже.

>>> a = 1/2/3/4/5/4/float(3)
>>> a
0.0

Если мы приведем последнее целое число к типу float, мы все равно получим ноль, поскольку к тому времени, когда наше число делится на float, уже становится 0 из-за целочисленного деления.

>>> a = 1/2/3/float(4)/5/4/3
>>> a
0.0

Тот же сценарий, что и выше, но смещение типа float немного ближе к левой стороне.

>>> a = float(1)/2/3/4/5/4/3
>>> a
0.0006944444444444445

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

Дополнительно 1: если вы пытаетесь ответить на этот вопрос, чтобы улучшить арифметическую оценку, вам следует проверить это

Дополнительно 2: Будьте осторожны со следующим сценарием:

>>> a = float(1/2/3/4/5/4/3)
>>> a
0.0

4

Определение числа с плавающей запятой с помощью символа '.' после числа также заставит его по умолчанию плавать.

>>> 1 / 2
0

>>> 1. / 2.
0.5

2

Сделайте хотя бы одно из них плавающим, тогда это будет деление с плавающей точкой, а не целое число:

>>> (20.0-10) / (100-10)
0.1111111111111111

Приведение результата в плавание уже слишком поздно.


1

В python cv2не обновлен расчет деления. Итак, вы должны включить from __future__ import division в первую строку программы.


0

В любом случае, это целочисленное деление. 10/90 = 0. Во втором случае вы просто преобразуете 0 в число с плавающей точкой.

Попробуйте преобразовать один из операндов "/" в тип float:

float(20-10) / (100-10)

0

Вы выполняете приведение в положение с плавающей точкой после того, как разделение уже произошло во втором примере. Попробуй это:

float(20-10) / float(100-10)

0

Я несколько удивлен, что никто не упомянул, что исходному плакату, возможно, нравились рациональные числа. Если вам это интересно, программа Sage на Python придет вам на помощь . (В настоящее время все еще основан на Python 2.x, хотя 3.x находится в стадии разработки.)

sage: (20-10) / (100-10)
1/9

Это решение не для всех, потому что он выполняет предварительный анализ, поэтому эти числа не являются числами int, а Integerэлементами класса Sage . Тем не менее, стоит упомянуть как часть экосистемы Python.


0

Лично я предпочел вставить 1. *в самом начале. Таким образом, выражение стало примерно таким:

1. * (20-10) / (100-10)

Поскольку я всегда делаю деление для какой-то формулы, например:

accuracy = 1. * (len(y_val) - sum(y_val)) / len(y_val)

поэтому просто добавить .0лайк невозможно 20.0. И в моем случае обертка float()может немного потерять читаемость.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.