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?

Adam Nelson
źródło
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
kennytm
źródło
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
Dave Webb
źródło
11

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

float(20 - 10) / (100 - 10)
A. Levy
źródło
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.

Harsha Vardhan
źródło
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
Jerzy
źródło
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
billmanH
źródło
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.

unbeli
źródło
1

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

Kavitha Raj
źródło
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)
Fred Larson
źródło
0

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

float(20-10) / float(100-10)
David M.
źródło
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.

kcrisman
źródło
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.

FredWe
źródło