Как я могу заставить деление быть плавающей точкой? Деление продолжает округляться до 0?

721

У меня есть два целых значения aи b, но мне нужно их соотношение в плавающей запятой. Я знаю это a < bи хочу вычислить a / b, поэтому, если я использую целочисленное деление, я всегда получу 0 с остатком от a.

Как я могу заставить cбыть числом с плавающей точкой в ​​Python в следующем?

c = a / b
Натан Феллман
источник
Просто обновитесь до Python 3.
Борис,

Ответы:

807

В Python 2 деление двух целых дает int. В Python 3 он создает плавающее число. Мы можем получить новое поведение, импортируя из __future__.

>>> from __future__ import division
>>> a = 4
>>> b = 6
>>> c = a / b
>>> c
0.66666666666666663
Майкл Фэрли
источник
13
Обратите внимание, что from __future__ import divisionдолжно быть в самом начале файла
Яннис
Также проблема в том, что если вам нужно целочисленное деление в одном месте, а деление с плавающей точкой в ​​другом месте файла ...
mercury0114
1
@ mercury0114: не проблема; вы просто используете, //когда хотите разделение по полу, и /когда вы хотите floatразделить «true» ( ).
ShadowRanger
715

Вы можете бросить, чтобы плавать, делая c = a / float(b). Если числитель или знаменатель - это число с плавающей точкой, то результат также будет.


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

Стив Траут
источник
195

Как заставить деление быть плавающей точкой в ​​Python?

У меня есть два целочисленных значения a и b, но мне нужно их соотношение в плавающей запятой. Я знаю, что a <b, и я хочу вычислить a / b, поэтому, если я использую целочисленное деление, я всегда получу 0 с остатком от a.

Как я могу заставить c быть числом с плавающей точкой в ​​Python в следующем?

c = a / b

Что действительно спрашивают здесь:

«Как мне заставить истинное деление таким, что a / bвернет дробь?»

Обновление до Python 3

В Python 3, чтобы получить истинное деление, вы просто делаете a / b.

>>> 1/2
0.5

Классическое деление по полу для целых чисел теперь a // b:

>>> 1//2
0
>>> 1//2.0
0.0

Тем не менее, вы можете застрять с использованием Python 2, или вы можете писать код, который должен работать как в 2 и 3.

Если использовать Python 2

В Python 2 это не так просто. Некоторые способы работы с классическим делением Python 2 лучше и надежнее, чем другие.

Рекомендация для Python 2

Вы можете получить поведение деления Python 3 в любом модуле со следующим импортом вверху:

from __future__ import division

который затем применяет деление стиля Python 3 на весь модуль. Он также работает в оболочке Python в любой точке. В Python 2:

>>> from __future__ import division
>>> 1/2
0.5
>>> 1//2
0
>>> 1//2.0
0.0

Это действительно лучшее решение, поскольку оно гарантирует, что код вашего модуля более совместим с Python 3.

Другие опции для Python 2

Если вы не хотите применять это ко всему модулю, вы ограничены несколькими обходными путями. Наиболее популярным является приведение одного из операндов в число с плавающей точкой. Одним из надежных решений является a / (b * 1.0). В новой оболочке Python:

>>> 1/(2 * 1.0)
0.5

Также надежный truedivиз operatorмодуля operator.truediv(a, b), но это, вероятно, медленнее, потому что это вызов функции:

>>> from operator import truediv
>>> truediv(1, 2)
0.5

Не рекомендуется для Python 2

Обычно это видно a / float(b). Это вызовет ошибку TypeError, если b - комплексное число. Поскольку деление с комплексными числами определено, для меня имеет смысл не допустить сбоя деления при передаче комплексного числа для делителя.

>>> 1 / float(2)
0.5
>>> 1 / float(2j)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't convert complex to float

Мне не имеет смысла целенаправленно делать ваш код более хрупким.

Вы также можете запускать Python с -Qnewфлагом, но у этого есть недостаток - выполнение всех модулей с новым поведением Python 3, и некоторые из ваших модулей могут ожидать классическое разделение, поэтому я не рекомендую этого, кроме как для тестирования. Но для демонстрации:

$ python -Qnew -c 'print 1/2'
0.5
$ python -Qnew -c 'print 1/2j'
-0.5j
Аарон Холл
источник
3
«1 // 2 = 0», «1 // 2.0 = 0.0» - интересная небольшая ошибка, даже если это целочисленное деление, если любой из операндов является плавающим, то результатом является целое число, но также и плавающее. Я использовал целочисленное деление для вычисления индекса списка и получил ошибку из-за этого.
Р. Навега
134
c = a / (b * 1.0)
карточная игра, напоминающая безик
источник
66

В Python 3.x одиночная косая черта ( /) всегда означает истинное (не усеченное) деление. ( //Оператор используется для усечения деления.) В Python 2.x (2.2 и выше) вы можете получить то же самое поведение, поставив

from __future__ import division

в верхней части вашего модуля.

newacct
источник
30

Создание любого из параметров для деления в формате с плавающей запятой также приводит к выводу в формате с плавающей запятой.

Пример:

>>> 4.0/3
1.3333333333333333

или,

>>> 4 / 3.0
1.3333333333333333

или,

>>> 4 / float(3)
1.3333333333333333

или,

>>> float(4) / 3
1.3333333333333333
gsbabil
источник
4
Но позже вы можете испытать искушение сделать 1.0 + 1/3или float(c) + a/bили float(a/b)и вы будете разочарованы ответом. Лучше использовать Python 3+ или импортировать __future__.divisionмодуль (см. Принятый ответ), чтобы всегда получить ожидаемый ответ. Существующие правила деления создают коварную, трудно прослеживаемую математическую ошибку.
варенье
@JoeCondron Вы пробовали python -c 'a=10; b=3.0; print a/b'?
gsbabil
Я не должен был, потому что это очевидно работает в этом сценарии. Однако что если aи 'b', например, являются выходами функции целочисленного значения? Например, a = len(list1), b = len(list2).
ДжоКондрон
@JoeCondron: хорошая мысль. Я только что обновил ответ, чтобы включить float(..). Я думаю, что умножение на 1.0, как предложил @Pinochle ниже, также может быть полезным.
gsbabil
21

Добавьте точку ( .) для обозначения чисел с плавающей точкой

>>> 4/3.
1.3333333333333333
Александр
источник
2
Как вы собираетесь применять этот подход, если числитель и знаменатель являются переменными?
stackoverflowuser2010
Я предполагаю, что вы ссылаетесь на первый пример, если это так, я бы просто использовал float()одну из переменных.
Александр
13

Это тоже будет работать

>>> u=1./5
>>> print u
0.2
Гаурав Агарвал
источник
4
И как вы собираетесь применять этот подход, если числитель и знаменатель являются переменными?
stackoverflowuser2010
1
Потому что это не работает, когда переменные используются для абстракции. Почти ни один значимый код не имеет таких жестко закодированных значений.
Кейр Симмонс
1
Это имеет мало голосов, потому что этот ответ не отвечает на вопрос, и не является общим ответом вообще. В ответе также важно сначала показать, почему это работает. Это очень просто: если числитель или знаменатель является числом с плавающей точкой, результатом будет число с плавающей точкой. Обычно вы не используете python в качестве калькулятора открытого текста, поэтому вам нужен ответ для переменных aи b.
ТимЗаман
Долгое время я думал, ./что в Python действительный оператор, который позволяет вам выполнять деление с плавающей запятой. Вот почему хорошо использовать пробелы разумно на любом языке программирования
smac89
6

Если вы хотите использовать «истинное» (с плавающей запятой) деление по умолчанию, есть флаг командной строки:

python -Q new foo.py

Есть некоторые недостатки (от PEP):

Утверждалось, что параметр командной строки для изменения значения по умолчанию является злом. Конечно, это может быть опасно в чужих руках: например, было бы невозможно объединить сторонний библиотечный пакет, который требует -Qnew, с другим, который требует -Qold.

Вы можете узнать больше о других значениях флагов, которые изменяют / предупреждают о поведении деления, посмотрев справочную страницу Python.

Для получения полной информации об изменениях деления читайте: PEP 238 - Изменение оператора деления

stephenbez
источник
2
from operator import truediv

c = truediv(a, b)
JoeCondron
источник
2
Это не идеально, так как это не работает в случае, когда aint и bfloat. Лучшее решение в том же духе - это сделать, from operator import truedivа затем использовать truediv(a, b).
Марк Дикинсон
Да, ты прав. Я предполагал оба целых числа, поскольку это единственный раз, когда операции разделения отличаются, но вы действительно хотите общее решение. На самом деле я не знал, что вы могли бы импортировать оператор или что он вообще не работает для делителей поплавка. Ответ отредактирован.
ДжоКондрон
1
from operator import truediv

c = truediv(a, b)

где а - дивиденд, а б - делитель. Эта функция удобна, когда частным после деления двух целых чисел является число с плавающей точкой.

Четан Йеши
источник