Bölünmeyi kayan nokta olmaya nasıl zorlayabilirim? Division 0'a yuvarlamaya devam ediyor mu?


721

İki tamsayı değerim var ave bkayan noktadaki oranlarına ihtiyacım var. Bunu biliyorum a < bve hesaplamak istiyorum a / b, bu yüzden tamsayı bölme kullanırsam, her zaman geri kalanıyla 0 alırım a.

cAşağıda Python'da kayan nokta sayısı olmaya nasıl zorlayabilirim ?

c = a / b

Sadece Python 3'e yükseltin.
Boris

Yanıtlar:


807

Python 2'de, iki intun bölünmesi bir int üretir. Python 3'te bir şamandıra üretir. Yeni davranışı içe aktararak elde edebiliriz __future__.

>>> from __future__ import division
>>> a = 4
>>> b = 6
>>> c = a / b
>>> c
0.66666666666666663

13
from __future__ import divisionDosyanın en başında olması gerektiğini unutmayın
yannis

Ayrıca sorun tamsayı bölümü bir yerde ama şamandıra bölümü başka bir yerde
istiyorsanız

1
@ mercury0114: Sorun değil; sadece //kat bölümü istediğinizde ve /"doğru" ( float) bölüm istediğinizde kullanın .
ShadowRanger

715

Yaparak şamandıraya dökebilirsiniz c = a / float(b). Pay veya payda bir şamandıra ise, sonuç da olacaktır.


Bir uyarı: yorum yapanların işaret ettiği gibi, bbir tam sayı veya kayan nokta sayısı (veya birini temsil eden bir dize) dışında bir şey olabilirse bu işe yaramaz . Başka türlerle (karmaşık sayılar gibi) uğraşıyorsanız, bunları kontrol etmeniz veya farklı bir yöntem kullanmanız gerekir.


195

Python'da bölünmeyi kayan nokta olmaya nasıl zorlayabilirim?

İki tamsayı a ve b var, ancak kayan noktadaki oranlarına ihtiyacım var. Ben a <b ve ben a / b hesaplamak istiyorum biliyorum, bu yüzden eğer tamsayı bölümü kullanırsanız her zaman bir geri kalanı ile 0 alırsınız.

Aşağıda c'yi Python'da kayan nokta sayısı olmaya nasıl zorlayabilirim?

c = a / b

Burada gerçekten sorulan şey:

"Gerçek bölünmeyi a / bkesir döndürecek şekilde nasıl zorlarım?"

Python 3'e yükseltme

Python 3'te, gerçek bölünme elde etmek için yapmanız yeterlidir a / b.

>>> 1/2
0.5

Tamsayılar için klasik bölme davranışı olan kat bölümü şimdi a // b:

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

Ancak, Python 2 ile sıkışmış olabilir veya hem 2 hem de 3'te çalışması gereken bir kod yazıyor olabilirsiniz.

Python 2 Kullanıyorsanız

Python 2'de bu o kadar basit değil. Klasik Python 2 bölümüyle baş etmenin bazı yolları diğerlerinden daha iyi ve daha sağlamdır.

Python 2 için öneri

Python 3 bölüm davranışını, aşağıdaki içe aktarma işlemi üstte olacak şekilde herhangi bir modülde alabilirsiniz:

from __future__ import division

daha sonra tüm modüle Python 3 stil bölümü uygulanır. Ayrıca herhangi bir noktada bir python kabuğunda çalışır. Python 2'de:

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

Modülünüzdeki kodun Python 3 ile daha ileri uyumlu olmasını sağladığından bu gerçekten en iyi çözümdür.

Python 2 için diğer seçenekler

Bunu tüm modüle uygulamak istemiyorsanız, birkaç geçici çözümle sınırlısınız. En popüler olanı, işlenenlerden birini bir şamandıraya zorlamaktır. Sağlam bir çözüm a / (b * 1.0). Taze bir Python kabuğunda:

>>> 1/(2 * 1.0)
0.5

Ayrıca sağlamdır truedivgelen operatormodül operator.truediv(a, b), ama bir işlev çağrısı çünkü bu büyük olasılıkla yavaştır:

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

Python 2 için Önerilmez

Yaygın olarak görülür a / float(b). B karmaşık bir sayı ise TypeError değerini yükseltir. Karmaşık sayılarla bölme tanımlandığından, bölen için karmaşık bir sayıyı geçtiğinde bölme işleminin başarısız olması bana mantıklı geliyor.

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

Kodunuzu bilerek daha kırılgan hale getirmek benim için çok mantıklı değil.

Python'u -Qnewbayrakla da çalıştırabilirsiniz , ancak bunun tüm modülleri yeni Python 3 davranışı ile yürütmenin dezavantajı vardır ve bazı modülleriniz klasik bölme bekleyebilir, bu yüzden test dışında bunu önermiyorum. Ama göstermek için:

$ 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" - ilginç küçük gotcha, bir tamsayı bölümü olsa bile, işlenenlerden herhangi biri kayarsa, sonuç bir tam sayıdır ancak aynı zamanda kayar. Bir liste dizini hesaplamak ve bu nedenle bir hata almak için bir tamsayı bölümü kullanıyordum.
R. Navega


66

Python 3.x'te, tek eğik çizgi ( /) her zaman doğru (kesmeyen) bölme anlamına gelir. ( //Operatör bölünmeyi kısaltmak için kullanılır.) Python 2.x (2.2 ve üstü) sürümlerinde,

from __future__ import division

tıklayın.


30

Kayan nokta biçiminde bölme için herhangi bir parametreyi yapmak, aynı zamanda çıktı noktasında da çıktı üretir.

Misal:

>>> 4.0/3
1.3333333333333333

veya,

>>> 4 / 3.0
1.3333333333333333

veya,

>>> 4 / float(3)
1.3333333333333333

veya,

>>> float(4) / 3
1.3333333333333333

4
Ancak daha sonra yapmaya cazip gelebilir 1.0 + 1/3ya float(c) + a/bda ya da float(a/b)cevaptan hayal kırıklığına uğrayacaksınız. __future__.divisionHer zaman beklediğiniz yanıtı almak için python 3+ kullanmak veya modülü almak daha iyidir (kabul edilen cevaba bakınız). Mevcut bölüm kuralları sinsi, izlemesi zor bir matematik hatası yaratır.
Ocaklar

@JoeCondron Denediniz mi python -c 'a=10; b=3.0; print a/b'?
gsbabil

Bunu yapmak zorunda değildim çünkü bu senaryoda açıkça işe yarıyor. Ancak, ne ave 'b', örneğin bir tamsayı-değer fonksiyonunun çıktılarıdır? Ör a = len(list1), b = len(list2).
JoeCondron

@ JoeCondron: iyi bir nokta. Cevabı eklemek için güncelledim float(..). Ben ile çarpılması düşünüyorum 1.0@Pinochle aşağıda belirtildiği gibi ayrıca yararlı olabilir,.
gsbabil

21

.Kayan nokta sayılarını belirtmek için nokta ( ) ekleyin

>>> 4/3.
1.3333333333333333

2
Pay ve payda ikisi de değişkense bu yaklaşımı nasıl uygulayacaksınız?
stackoverflowuser2010

İlk örneğe başvurduğunuzu varsayıyorum, eğer öyleyse, sadece float()değişkenlerden birinde kullanırım .
Alexander

13

Bu da işe yarayacak

>>> u=1./5
>>> print u
0.2

4
Peki pay ve payda her iki değişken ise bu yaklaşımı nasıl uygulayacaksınız?
stackoverflowuser2010

1
Çünkü değişkenler soyutlama için kullanıldığında çalışmaz. Neredeyse hiçbir anlamlı kodun bu şekilde kodlanmış değerleri yoktur.
Keir Simmons

1
Bunun çok az oyu var, çünkü bu cevap soruya cevap vermiyor ve genel bir cevap değil. Bir cevapta, bunun neden işe yaradığını göstermek de ilk önce önemlidir. Çok basit: pay veya payda bir şamandıra ise, sonuç bir şamandıra olacaktır. Genellikle python'u düz metin hesap makinesi olarak kullanmazsınız, bu nedenle değişkenler ave için bir cevap istersiniz b.
TimZaman

En uzun süre, aslında ./python'da kayan nokta bölme yapmanızı sağlayan geçerli bir operatör olduğunu düşündüm . Bu nedenle beyaz alanı herhangi bir programlama dilinde akıllıca kullanmak iyidir
smac89

6

Varsayılan olarak "true" (kayan nokta) bölünmesini kullanmak istiyorsanız, bir komut satırı bayrağı vardır:

python -Q new foo.py

Bazı dezavantajlar vardır (PEP'ten):

Varsayılanı değiştirmek için bir komut satırı seçeneğinin kötü olduğu ileri sürülmüştür. Yanlış ellerde kesinlikle tehlikeli olabilir: örneğin, -Qnew gerektiren bir 3. taraf kütüphane paketini -Qold gerektiren başka bir kütüphane ile birleştirmek imkansızdır.

Python man sayfasına bakarak bölme davranışını değiştiren / uyaran diğer bayrak değerleri hakkında daha fazla bilgi edinebilirsiniz.

Bölme değişiklikleriyle ilgili tüm ayrıntılar için PEP 238 - Bölüm Operatörünü Değiştirme


2
from operator import truediv

c = truediv(a, b)

2
Yine de bu ideal değildir, çünkü aint ve bfloat olduğu durumlarda çalışmaz . Aynı hatlar boyunca daha iyi bir çözüm yapmak from operator import truedivve kullanmaktır truediv(a, b).
Mark Dickinson

Evet, haklısın. Her iki tamsayıyı da varsayıyordum, çünkü bölüm op'larının farklı olduğu tek zaman bu, ancak gerçekten genel bir çözüm istiyorsunuz. Operatörü içe aktarabileceğinizi veya şamandıra bölücüler için hiç işe yaramayacağını bilmiyordum. Yanıt düzenlendi.
JoeCondron

1
from operator import truediv

c = truediv(a, b)

burada a temettü ve b bölücüdür. Bu fonksiyon, iki tamsayının bölünmesinden sonraki bölüm bir kayan nokta olduğunda kullanışlıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.