Podział Pythona


134

Próbowałem znormalizować zbiór liczb od -100 do 0 do zakresu 10-100 i miałem problemy tylko po to, aby zauważyć, że nawet bez żadnych zmiennych nie ocenia to w sposób, w jaki bym się tego spodziewał:

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

Podział pływający też nie działa:

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

Jeśli dowolna strona podziału zostanie rzucona na pływak, zadziała:

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

Każda strona w pierwszym przykładzie jest oceniana jako int, co oznacza, że ​​ostateczna odpowiedź zostanie rzutowana na int. Ponieważ 0,111 to mniej niż 0,5, zaokrągla się do 0. Moim zdaniem nie jest przezroczysty, ale myślę, że tak właśnie jest.

Jakie jest wyjaśnienie?



3
Adam, nadal nie podoba mi się twoje wyjaśnienie. Pierwszym przykładem jest dzielenie liczb całkowitych, które po prostu zwraca 0. Drugi przykład jest nieprawidłowo umieszczony w nawiasach dla żądanego efektu.
Prezydent James K. Polk

@GregS Pierwszym przykładem był problem. Drugi przykład ma charakter wyjaśniający i został napisany po pierwszym pytaniu. Wszystkie poniższe odpowiedzi bardzo dobrze wyjaśniają problem, zwłaszcza @KennyTM. Ważne jest, aby zauważyć, że mój pierwotny problem dotyczy tylko Pythona 2.x, a nie 3. To trochę niepokojące, że zachowanie zmieni się w ten sposób, ale teraz, gdy wiem, użyję z przyszłego podziału importu i użyję 3 .x zachowanie. Twoje zdrowie.
Adam Nelson

1
Adam, popraw ostatnią EDYCJĘ. Prawa strona nie ma w tym nic specjalnego; aby dzielenie było zmiennoprzecinkowe, albo licznik, albo mianownik (lub oba) muszą być zmienne. Jeśli uważasz, że przeczytałeś w dokumentacji, że prawa strona musi być zmienna, to albo dokumentacja jest źle sformułowana i powinna zostać poprawiona, albo źle ją zrozumiałeś. Czy widziałeś być może przykład, a następnie ekstrapolowałeś z niego regułę?
tzot

Odpowiedzi:


246

Używasz języka Python 2.x, w którym podziały w liczbach całkowitych zostaną obcięte, zamiast stać się liczbą zmiennoprzecinkową.

>>> 1 / 2
0

Powinieneś zrobić z jednego z nich float:

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

lub from __future__ import division, który wymusza /przyjęcie zachowania Pythona 3.x, które zawsze zwraca wartość zmiennoprzecinkową.

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

10
Jeśli używasz from __future__ import division, możesz uzyskać podział na stary styl C, używając dwóch ukośników (np. 1 // 2Spowoduje 0). Zobacz Pep 238 Changing the Division Operator
User

1
@User Nie ma potrzeby importowania z __future__. W obu Python 2 i 3 //odnosi się __floordiv__()domyślnie.
Casimir

21

Jesteś wprowadzenie liczb całkowitych więc Python daje Ci plecy całkowitą :

>>> 10 / 90
0

Jeśli później rzucisz to na zmiennoprzecinkowe, zaokrąglenie zostanie już wykonane, innymi słowy, liczba całkowita 0 zawsze stanie się liczbą zmiennoprzecinkową 0.

Jeśli użyjesz liczb zmiennoprzecinkowych po obu stronach podziału, Python udzieli odpowiedzi, której oczekujesz.

>>> 10 / 90.0
0.1111111111111111

Więc w twoim przypadku:

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

11

Musisz zmienić go na zmiennoprzecinkowy PRZED dzieleniem. To jest:

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

4
@Adam Nelson: U mnie działa poprawnie. Sprawdź nawiasy.
Fred Larson

Właściwie to się mylę - ale po obejrzeniu dokumentów, należy najpierw rzucić prawą stronę.
Adam Nelson

10
@Adam: Nie ma znaczenia, która strona pierwsza.
kennytm

11

W Pythonie 2.7 /operatorem jest dzielenie liczb całkowitych, jeśli dane wejściowe są liczbami całkowitymi:

>>>20/15
1

>>>20.0/15.0
1.33333333333

>>>20.0/15
1.33333333333

W Pythonie 3.3 /operator jest dzieleniem typu float, nawet jeśli dane wejściowe są liczbami całkowitymi.

>>> 20/15
1.33333333333

>>>20.0/15
1.33333333333

Do dzielenia liczb całkowitych w Pythonie 3 użyjemy //operatora.

//Operator operator dzielenia całkowitego zarówno Pythonie 2,7 Python 3.3.

W Pythonie 2.7 i Pythonie 3.3:

>>>20//15
1

A teraz zobacz porównanie

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

W przypadku powyższego programu wynik będzie miał wartość False w Pythonie 2.7 i True w Pythonie 3.3.

W Pythonie 2.7 a = 1,75 ib = 1.

W Pythonie 3.3 a = 1,75 i b = 1,75, tylko dlatego, że /jest to dzielenie typu float.


8

Ma to związek z wersją Pythona, której używasz. Zasadniczo przyjmuje zachowanie C: jeśli podzielisz dwie liczby całkowite, wyniki zostaną zaokrąglone w dół do liczby całkowitej. Pamiętaj również, że Python wykonuje operacje od lewej do prawej, co odgrywa rolę podczas pisania na maszynie.

Przykład: Ponieważ jest to pytanie, które zawsze pojawia się w mojej głowie, gdy wykonuję operacje arytmetyczne (czy powinienem przekonwertować na liczbę zmiennoprzecinkową i jaką liczbę), przedstawiono przykład z tego aspektu:

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

Kiedy dzielimy liczby całkowite, nie jest zaskakujące, że jest zaokrąglany od dołu.

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

Jeśli wpiszemy ostatnią liczbę całkowitą do liczby zmiennoprzecinkowej, nadal otrzymamy zero, ponieważ do czasu, gdy nasza liczba zostanie podzielona przez liczbę zmiennoprzecinkową, już wynosi 0 z powodu dzielenia liczb całkowitych.

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

Taki sam scenariusz jak powyżej, ale przesunięcie typu float nieco bliżej lewej strony.

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

Na koniec, kiedy typujemy pierwszą liczbę całkowitą do float, wynik jest pożądany, ponieważ zaczynając od pierwszego dzielenia, czyli od lewej, używamy liczb zmiennoprzecinkowych.

Dodatek 1: Jeśli próbujesz odpowiedzieć na to pytanie, aby poprawić ocenę arytmetyczną, powinieneś to sprawdzić

Dodatek 2: Uważaj na następujący scenariusz:

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

4

Określanie pływaka poprzez umieszczenie znaku „.” po liczbie spowoduje również, że domyślnie będzie się unosić.

>>> 1 / 2
0

>>> 1. / 2.
0.5

2

Niech przynajmniej jeden z nich będzie pływający, wtedy będzie to dzielenie typu float, a nie liczba całkowita:

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

Rzucanie wyniku na float jest za późno.


1

W Pythonie cv2nie zaktualizowano obliczeń podziału. więc musisz uwzględnić from __future__ import division w pierwszej linii programu.


0

Tak czy inaczej, jest to dzielenie liczb całkowitych. 10/90 = 0. W drugim przypadku po prostu rzucasz 0 do float.

Spróbuj rzutować jeden z operandów „/” na zmiennoprzecinkowy:

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

0

Rzucasz na float po tym, jak w drugim przykładzie już nastąpił podział. Spróbuj tego:

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

0

Jestem nieco zaskoczony, że nikt nie wspomniał, że oryginalny plakat mógł spodobać się racjonalnym liczbom. Jeśli jesteś tym zainteresowany, program Sage oparty na języku Python będzie Cię wspierał . (Obecnie nadal oparty na Pythonie 2.x, chociaż 3.x jest w toku.)

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

To nie jest rozwiązanie dla wszystkich, ponieważ wykonuje pewne przygotowania, więc te liczby nie są ints, ale Integerelementami klasy Sage . Mimo to warto o tym wspomnieć jako część ekosystemu Pythona.


0

Osobiście wolałem wstawić a 1. *na samym początku. Więc wyrażenie wygląda mniej więcej tak:

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

Jak zawsze robię podział dla jakiejś formuły, takiej jak:

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

więc nie można po prostu dodać .0polubienia 20.0. A w moim przypadku owijanie z float()może trochę stracić na czytelności.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.