Jak wymusić podział na zmiennoprzecinkowy? Podział zaokrągla w dół do 0?

721

Mam dwie wartości całkowite ai b, ale potrzebuję ich stosunku w liczbach zmiennoprzecinkowych. Wiem o tym a < bi chcę obliczyć a / b, więc jeśli użyję dzielenia liczb całkowitych, zawsze otrzymam 0 z resztą a.

Jak mogę zmusić się cdo bycia liczbą zmiennoprzecinkową w Pythonie poniżej?

c = a / b
Nathan Fellman
źródło
Po prostu uaktualnij do Pythona 3.
Boris

Odpowiedzi:

807

W Pythonie 2 podział dwóch liczb całkowitych tworzy liczbę całkowitą. W Pythonie 3 tworzy liczbę zmiennoprzecinkową. Nowe zachowanie możemy uzyskać, importując z __future__.

>>> from __future__ import division
>>> a = 4
>>> b = 6
>>> c = a / b
>>> c
0.66666666666666663
Michael Fairley
źródło
13
Pamiętaj, że from __future__ import divisionmusi być na samym początku pliku
yannis
Problemem jest również to, że chcesz podzielić liczbę całkowitą w jednym miejscu, ale podział zmiennoprzecinkowy w innym miejscu pliku ...
mercury0114
1
@ mercury0114: To nie problem; po prostu używasz, //kiedy chcesz podzielić podłogę i /kiedy chcesz „prawdziwego” ( float) podziału.
ShadowRanger
715

Możesz rzucić na pływaka, wykonując c = a / float(b). Jeśli licznik lub mianownik jest liczbą zmiennoprzecinkową, wówczas wynik również będzie.


Zastrzeżenie: jak zauważyli komentatorzy, to nie zadziała, jeśli bmoże być czymś innym niż liczba całkowita lub liczba zmiennoprzecinkowa (lub ciąg reprezentujący jeden). Jeśli masz do czynienia z innymi typami (takimi jak liczby zespolone), musisz je sprawdzić lub użyć innej metody.

Steve Trout
źródło
195

Jak zmusić dzielenie do zmiennoprzecinkowego w Pythonie?

Mam dwie wartości całkowite a i b, ale potrzebuję ich stosunku w zmiennoprzecinkowej. Wiem, że a <b i chcę obliczyć a / b, więc jeśli użyję dzielenia liczb całkowitych, zawsze otrzymam 0 z resztą a.

Jak mogę zmusić c do bycia liczbą zmiennoprzecinkową w Pythonie?

c = a / b

Tak naprawdę pyta się tutaj:

„Jak wymusić prawdziwy podział, który a / bzwróci ułamek?”

Uaktualnij do Python 3

W Pythonie 3, aby uzyskać prawdziwy podział, wystarczy a / b.

>>> 1/2
0.5

Podział podłogi, klasyczne zachowanie podziału na liczby całkowite, jest teraz a // b:

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

Możesz jednak utknąć w Pythonie 2 lub pisać kod, który musi działać zarówno w 2, jak i 3.

Jeśli używasz języka Python 2

W Pythonie 2 nie jest to takie proste. Niektóre sposoby radzenia sobie z klasycznym działem Python 2 są lepsze i bardziej niezawodne niż inne.

Zalecenie dla Python 2

Możesz uzyskać zachowanie podziału Python 3 w dowolnym module z następującym importem u góry:

from __future__ import division

który następnie stosuje podział stylu Python 3 na cały moduł. Działa również w powłoce pytona w dowolnym punkcie. W Python 2:

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

To jest naprawdę najlepsze rozwiązanie, ponieważ zapewnia, że ​​kod w twoim module jest bardziej zgodny z Pythonem 3.

Inne opcje dla Python 2

Jeśli nie chcesz zastosować tego do całego modułu, ograniczasz się do kilku obejść. Najpopularniejszym jest zmuszenie jednego z operandów do wypłynięcia. Jednym z solidnych rozwiązań jest a / (b * 1.0). W nowej powłoce Pythona:

>>> 1/(2 * 1.0)
0.5

Solidny jest truedivrównież operatormoduł operator.truediv(a, b), ale jest to prawdopodobnie wolniejsze, ponieważ jest to wywołanie funkcji:

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

Niezalecane dla Python 2

Powszechnie widziany jest a / float(b). To spowoduje podniesienie błędu typu, jeśli b jest liczbą zespoloną. Ponieważ podział z liczbami zespolonymi jest zdefiniowany, dla mnie sensowne jest, aby brak podziału nie powiódł się po przekazaniu liczby zespolonej dla dzielnika.

>>> 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

Celowe zwiększenie kruchości kodu nie ma dla mnie sensu.

Możesz również uruchomić Python z -Qnewflagą, ale ma to wadę wykonywania wszystkich modułów za pomocą nowego zachowania Python 3, a niektóre z twoich modułów mogą oczekiwać klasycznego podziału, więc nie polecam tego poza testowaniem. Ale aby zademonstrować:

$ python -Qnew -c 'print 1/2'
0.5
$ python -Qnew -c 'print 1/2j'
-0.5j
Aaron Hall
źródło
3
„1 // 2 = 0”, „1 // 2.0 = 0.0” - interesująca mała gotcha, nawet jeśli jest to liczba całkowita, jeśli którykolwiek z argumentów jest liczbą zmiennoprzecinkową, wynikiem jest liczba całkowita, ale także liczba zmiennoprzecinkowa. Użyłem podziału liczb całkowitych do obliczenia indeksu listy i otrzymałem błąd z tego powodu.
R. Navega,
134
c = a / (b * 1.0)
Pinochle
źródło
66

W Pythonie 3.x pojedynczy ukośnik ( /) zawsze oznacza prawdziwy (nie obcięty) podział. ( //Operator służy do obcinania podziału.) W Pythonie 2.x (2.2 i nowszych) można uzyskać to samo zachowanie, umieszczając

from __future__ import division

u góry modułu.

newacct
źródło
30

Samo wykonanie dowolnego parametru do podziału w formacie zmiennoprzecinkowym powoduje również wygenerowanie wyniku w zmiennoprzecinkowym.

Przykład:

>>> 4.0/3
1.3333333333333333

lub,

>>> 4 / 3.0
1.3333333333333333

lub,

>>> 4 / float(3)
1.3333333333333333

lub,

>>> float(4) / 3
1.3333333333333333
gsbabil
źródło
4
Ale możesz później ulec pokusie zrobienia 1.0 + 1/3lub float(c) + a/blub float(a/b)i będziesz rozczarowany odpowiedzią. Lepiej użyć Pythona 3+ lub zaimportować __future__.divisionmoduł (patrz zaakceptowana odpowiedź), aby zawsze uzyskać oczekiwaną odpowiedź. Istniejące reguły podziału powodują podstępny, trudny do wyśledzenia błąd matematyczny.
płyty grzewcze
@JoeCondron Próbowałeś python -c 'a=10; b=3.0; print a/b'?
gsbabil
Nie musiałem, bo to oczywiście działa w tym scenariuszu. Co jednak, jeśli ai „b”, na przykład, są wyjściami funkcji wartości całkowitych? Np a = len(list1), b = len(list2).
JoeCondron
@JoeCondron: dobry punkt. Właśnie zaktualizowałem odpowiedź, aby ją uwzględnić float(..). Myślę, że mnożenie przez 1.0, jak sugeruje @ Pinochle poniżej, może być również przydatne.
gsbabil
21

Dodaj kropkę ( .), aby wskazać liczby zmiennoprzecinkowe

>>> 4/3.
1.3333333333333333
Alexander
źródło
2
Jak zamierzasz zastosować to podejście, jeśli zarówno licznik, jak i mianownik są zmiennymi?
stackoverflowuser2010
Zakładam, że odwołujesz się do pierwszego przykładu, jeśli tak jest, po prostu użyłbym float()jednej ze zmiennych.
Alexander
13

To też zadziała

>>> u=1./5
>>> print u
0.2
Gaurav Agarwal
źródło
4
I jak zamierzasz zastosować to podejście, jeśli licznik i mianownik są zmiennymi?
stackoverflowuser2010
1
Ponieważ nie działa, gdy zmienne są używane do abstrakcji. Prawie żaden znaczący kod nie ma tak zakodowanych wartości.
Keir Simmons
1
Ma niewiele głosów, ponieważ ta odpowiedź nie odpowiada na pytanie i wcale nie jest odpowiedzią ogólną. W odpowiedzi ważne jest również, aby najpierw pokazać, dlaczego to działa. To bardzo proste: jeśli licznik lub mianownik jest liczbą zmiennoprzecinkową, wynikiem będzie liczba zmiennoprzecinkowa. Zwykle nie używasz Pythona jako kalkulatora w postaci zwykłego tekstu, więc potrzebujesz odpowiedzi na zmienne ai b.
TimZaman,
Najdłużej myślałem, że ./jest poprawnym operatorem w pythonie, który pozwala na dzielenie zmiennoprzecinkowe. Dlatego dobrze jest rozsądnie wykorzystywać białe
znaki
6

Jeśli chcesz domyślnie używać podziału „prawda” (zmiennoprzecinkowa), dostępna jest flaga wiersza polecenia:

python -Q new foo.py

Istnieją pewne wady (z PEP):

Argumentowano, że opcja zmiany domyślnej linii poleceń jest zła. Z pewnością może być niebezpieczny w niewłaściwych rękach: na przykład niemożliwe byłoby połączenie pakietu biblioteki innej firmy, który wymaga -Qnew z innym, który wymaga -Qold.

Możesz dowiedzieć się więcej o innych wartościach flag, które zmieniają / ostrzegają o zachowaniu dzielenia, patrząc na stronę podręcznika Pythona.

Aby uzyskać szczegółowe informacje na temat zmian podziału, przeczytaj: PEP 238 - Zmiana operatora podziału

Stephenbez
źródło
2
from operator import truediv

c = truediv(a, b)
JoeCondron
źródło
2
Nie jest to jednak idealne, ponieważ nie działa w przypadku, agdy int bjest i jest zmiennoprzecinkowe. Lepszym rozwiązaniem według tych samych zasad jest zrobienie, from operator import truediva następnie użycie truediv(a, b).
Mark Dickinson
Tak, masz rację. Zakładałem obie liczby całkowite, ponieważ jest to jedyny czas, kiedy operacje dywizji różnią się, ale naprawdę chcesz ogólnego rozwiązania. Nie wiedziałem, że możesz zaimportować operatora lub że w ogóle nie działa on dla dzielników typu float. Odpowiedź edytowana.
JoeCondron
1
from operator import truediv

c = truediv(a, b)

gdzie a jest dywidendą, a b jest dzielnikiem. Ta funkcja jest przydatna, gdy iloraz po podzieleniu dwóch liczb całkowitych jest liczbą zmiennoprzecinkową.

Chetan Yeshi
źródło