Sayıyı en yakın tam sayıya yuvarla


230

Ben gibi uzun şamandıra sayıları yuvarlamaya çalışıyorum:

32.268907563;
32.268907563;
31.2396694215;
33.6206896552;
...

Şimdiye kadar hiçbir başarı ile. Denedim math.ceil(x), math.floor(x)(bu yukarı veya aşağı yuvarlansa da, aradığım round(x)şey bu değildi ) ve hangisi de işe yaramadı (hala sayıları yüzer).

Ne yapabilirdim?

DÜZENLEME: KOD:

for i in widthRange:
    for j in heightRange:
        r, g, b = rgb_im.getpixel((i, j))
        h, s, v = colorsys.rgb_to_hsv(r/255.0, g/255.0, b/255.0)
        h = h * 360
        int(round(h))
        print(h)

3
Ben denerimint(x)
The Brofessor

bu hata vermez mi? 10 tabanlı int () için geçersiz değişmez değer:
snh_nl

Yanıtlar:


368
int(round(x))

Yuvarlar ve tamsayı olarak değiştirir

DÜZENLE:

Hiçbir değişkene int (round (h)) atamıyorsunuz. İnt (round (h)) öğesini çağırdığınızda, tam sayı değerini döndürür ancak başka bir şey yapmaz; bu satırı şu şekilde değiştirmeniz gerekir:

h = int(round(h))

Yeni değeri h değerine atamak için

DÜZENLEME 2:

@Plowman'ın yorumlarda söylediği gibi, Python'lar round()normalde beklendiği gibi çalışmaz ve bunun nedeni sayının bir değişken olarak depolanma biçiminin genellikle ekranda gördüğünüz gibi olmamasıdır. Bu davranışı açıklayan birçok cevap vardır:

round () düzgün yuvarlanmıyor gibi görünüyor

Bu sorunu önlemenin bir yolu, şu cevapta belirtildiği şekilde Ondalık değerini kullanmaktır: https://stackoverflow.com/a/15398691/4345659

Bu cevabın ekstra kütüphane kullanmadan düzgün çalışması için özel bir yuvarlama fonksiyonu kullanmak uygun olacaktır. Birçok düzeltmeden sonra, test ettiğim kadarıyla tüm depolama sorunlarından kaçınan aşağıdaki çözümü buldum. repr()(NOT str()!) İle elde edilen dize temsilini kullanmaya dayanır . Keskin görünüyor ama tüm davaları çözmenin tek yolu buydu. Hem Python2 hem de Python3 ile çalışır.

def proper_round(num, dec=0):
    num = str(num)[:str(num).index('.')+dec+2]
    if num[-1]>='5':
        return float(num[:-2-(not dec)]+str(int(num[-2-(not dec)])+1))
    return float(num[:-1])

Testler:

>>> print(proper_round(1.0005,3))
1.001
>>> print(proper_round(2.0005,3))
2.001
>>> print(proper_round(3.0005,3))
3.001
>>> print(proper_round(4.0005,3))
4.001
>>> print(proper_round(5.0005,3))
5.001
>>> print(proper_round(1.005,2))
1.01
>>> print(proper_round(2.005,2))
2.01
>>> print(proper_round(3.005,2))
3.01
>>> print(proper_round(4.005,2))
4.01
>>> print(proper_round(5.005,2))
5.01
>>> print(proper_round(1.05,1))
1.1
>>> print(proper_round(2.05,1))
2.1
>>> print(proper_round(3.05,1))
3.1
>>> print(proper_round(4.05,1))
4.1
>>> print(proper_round(5.05,1))
5.1
>>> print(proper_round(1.5))
2.0
>>> print(proper_round(2.5))
3.0
>>> print(proper_round(3.5))
4.0
>>> print(proper_round(4.5))
5.0
>>> print(proper_round(5.5))
6.0
>>> 
>>> print(proper_round(1.000499999999,3))
1.0
>>> print(proper_round(2.000499999999,3))
2.0
>>> print(proper_round(3.000499999999,3))
3.0
>>> print(proper_round(4.000499999999,3))
4.0
>>> print(proper_round(5.000499999999,3))
5.0
>>> print(proper_round(1.00499999999,2))
1.0
>>> print(proper_round(2.00499999999,2))
2.0
>>> print(proper_round(3.00499999999,2))
3.0
>>> print(proper_round(4.00499999999,2))
4.0
>>> print(proper_round(5.00499999999,2))
5.0
>>> print(proper_round(1.0499999999,1))
1.0
>>> print(proper_round(2.0499999999,1))
2.0
>>> print(proper_round(3.0499999999,1))
3.0
>>> print(proper_round(4.0499999999,1))
4.0
>>> print(proper_round(5.0499999999,1))
5.0
>>> print(proper_round(1.499999999))
1.0
>>> print(proper_round(2.499999999))
2.0
>>> print(proper_round(3.499999999))
3.0
>>> print(proper_round(4.499999999))
4.0
>>> print(proper_round(5.499999999))
5.0

Son olarak, düzeltilmiş cevap:

# Having proper_round defined as previously stated
h = int(proper_round(h))

DÜZENLEME 3:

Testler:

>>> proper_round(6.39764125, 2)
6.31 # should be 6.4
>>> proper_round(6.9764125, 1)
6.1  # should be 7

Buradaki gotcha, decondalık ondalık sayı 9 olabilir ve eğer dec+1sayı basamağı> = 5 ise, sayı 0 olur ve dec-1sayı basamağa bir 1 taşınmalıdır .

Bunu dikkate alırsak:

def proper_round(num, dec=0):
    num = str(num)[:str(num).index('.')+dec+2]
    if num[-1]>='5':
      a = num[:-2-(not dec)]       # integer part
      b = int(num[-2-(not dec)])+1 # decimal part
      return float(a)+b**(-dec+1) if a and b == 10 else float(a+str(b))
    return float(num[:-1])

Yukarıda tarif edilen durumda b = 10ve önceki versiyon sadece bir araya gelecek ave bbu 10da takip eden 0'ın nerede kaybolacağı bir birleşme ile sonuçlanacaktır . Bu sürüm uygun bir taşıma olarak bdoğru ondalık basamağa dönüşür dec.


2
print ("4.5)", int (round (4.5))) # bana 4 print ("5.5)", int (round (5.5)) verdi # # 6 verdi: (
Komm

Python sürümü ile ilgilidir. Bana Python 2.7.9 kullanarak 5 ve 6 ve dediğin gibi Python 3.4.2 kullanarak 4 ve 6
francisco sollima

1
Dikkat çekmeye değer: Bu çözüm muhtemelen beklediğiniz şekilde yuvarlanmaz. Örneğin, int(round(4.5))aşağı 4'e mermi iken int(round(4.500001))5. doğru mermi
saban

Eğer bir tamsayı istiyorsanız round(x)Python 3.6.2'de (ve belki de daha düşük versiyonlarda) yeterlidir. Sonuç zaten int türündedir. Not: round(x, n)şamandıra tipinde olacaktır.
Elmex80s

1
Bu, 112439.50093565206 için geçerli değildir. O / p -> 11253.0 verir. Kahretsin garip .. !!!!
ajin

24

Kullanın round(x, y). Numaranızı istediğiniz ondalık basamağa yuvarlar.

Örneğin:

>>> round(32.268907563, 3)
32.269

20

round(value,significantDigit)ancak bu, yuvarlak değerler sona erdiğinde matematik perspektifinden beklendiği gibi çalışmaz 5. Eğer 5yuvarlandığınız değerden hemen sonraki basamaktaysa, bu değerler bazen beklendiği gibi yuvarlanır (yani 8.005iki ondalık basamağa yuvarlama verir 8.01). Kayan nokta matematiğinin tuhaflıkları nedeniyle belirli değerler için bunlar yuvarlanır!

yani

>>> round(1.0005,3)
1.0
>>> round(2.0005,3)
2.001
>>> round(3.0005,3)
3.001
>>> round(4.0005,3)
4.0
>>> round(1.005,2)
1.0
>>> round(5.005,2)
5.0
>>> round(6.005,2)
6.0
>>> round(7.005,2)
7.0
>>> round(3.005,2)
3.0
>>> round(8.005,2)
8.01

Tuhaf.

Amacınız, bilimlerde istatistik için geleneksel yuvarlama yapmak olduğunu varsayarsak, bu, roundfonksiyonun beklendiği importgibi ekstra şeylere ihtiyaç duyduğu şekilde çalışmasını sağlamak için kullanışlı bir pakettir Decimal.

>>> round(0.075,2)

0.07

>>> round(0.075+10**(-2*5),2)

0.08

Aha! Buna dayanarak bir işlev yapabiliriz ...

def roundTraditional(val,digits):
   return round(val+10**(-len(str(val))-1), digits)

Temel olarak, bu, kullanmaya çalıştığınız dizenin en az verilen basamağından daha küçük olduğu garanti edilen bir değer ekler round. Az miktarda da en koruması yönünde ekleyerek roundşimdi sağlarken bir varlığa aşağı haneli etmektir yuvarlanır eğer, çoğu durumda 'ın davranışı 5o kadar yuvarlar ve eğer 4aşağı yuvarlar.

Kullanım yaklaşımı 10**(-len(val)-1), kaymayı zorlamak için ekleyebileceğiniz en büyük küçük sayı olduğu için kasıtlıydı, ayrıca eklediğiniz değerin, ondalık .eksik olmasa bile yuvarlamayı asla değiştirmediğinden emin olun . Ben daha fazla çıkarmak için sadece 10**(-len(val))bir koşullu if (val>1)kullanabilirsiniz 1... ama her zaman çıkarma basittir, 1çünkü bu geçici çözümün işleyebileceği geçerli ondalık sayı aralığını çok fazla değiştirmez. Değerleriniz türün sınırlarına ulaşırsa bu yaklaşım başarısız olur, bu başarısız olur, ancak geçerli ondalık değerlerin neredeyse tamamı için çalışması gerekir.

Bunu yapmak için ondalık kütüphaneyi de kullanabilirsiniz , ancak önerdiğim sarıcı daha basittir ve bazı durumlarda tercih edilebilir.


Düzenleme: Saçak durumda sadece belirli değerler için olduğunu gösteren işaret için teşekkürler Blckknght5 . Ayrıca bu cevabın daha önceki bir versiyonu, tek yuvarlama davranışının yalnızca5 yuvarladığınız basamağın hemen altında olan rakamın bir .


Ondalık sayıları neden 5son basamakları her zaman yuvarlanacak diye düşündüğünüzden emin değilim . Ben tıpkı sayılarla yaptığımız hızlı bir testte böyle değil 1.5, 2.5, 3.5ve benzeri ve 1.05, 1.15, 1.25, 1.35onluk bir düzeye yuvarlama. İlk küme (küçük tamsayılara yuvarlanan tam yarılar) her zaman eşit bir tamsayıya yuvarlanır. İkinci küme, muhtemelen bazı değerlerin hatalı ikili gösterimleri nedeniyle tutarlı bir şekilde yuvarlanmaz. Tam ikili temsillere sahip şamandıralar, 1.25en az anlamlı bir basamağa sahip olmak gibi yuvarlaktır, ancak diğerleri rastgele yuvarlanır.
Blckknght

İlginç ... haklısın. round(4.0005,3)verir 4.0ve round(1.0005,3)verir 1.0, ama round(2.0005,3)verir 2.001ve round(3.0005,3)verir 3.001. Ama tam da bu yüzden önerilen çözümüm gerekli ... bu önemli durumda hisse senedi turundan ne bekleyeceğinizi bilmiyorsunuz!
Jason R. Mick

Bunun için teşekkürler. Bu sorun ortaya çıktığında işleviniz kullanışlı olacaktır.
TMWP

1
, digitsBu iade beyanının sonunda mı demek istediniz ? Hiçbir cinas amaçlanan. ( ortalama demek istediğim)
user3342816 20:18

Ah doğru, gerçekten de orada olmalıydı. İyi yakalamak ... kimse fark etmedi şaşırttı! Çözümü kullananlar biraz hayal kırıklığı kurtaracak. :-)
Jason R. Mick

15

Pozitifler için deneyin

int(x + 0.5)

Negatifler için de işe yaraması için,

int(x + (0.5 if x > 0 else -0.5))

int()zemin işlevi gibi çalışır ve bu nedenle bu özellikten yararlanabilirsiniz. Bu kesinlikle en hızlı yoldur.


4
negatifler için çalışmıyor>>> x=-0.999 >>> int(x), round(x), int(x+0.5) (0, -1.0, 0)
user2907934

3
Köşe kasalarını önemsiyorsanız, "0,5 ve kat ekle" tekniğini kullanmayın - beklediğiniz gibi olmayan bazı değerler vardır! Bkz stackoverflow.com/a/47302585/2732969 almak ++ bir C ve için stackoverflow.com/a/38744026/2732969 bu çok soru cevap.
Anon

Hızlı bir yönteme ihtiyacım vardı, doğru olmak zorunda değildi ve birçok köşe vakası olmazdı ve köşe vakalarındaki hata senaryomda önemli değil. Bu kesinlikle hızın öncelikli olduğu bazı özel durumlar için gitmem. Hassasiyet veya doğruluk için önermeyin.
AgentM

11

IEEE 754'ün öngördüğü gibi, sadece Python yarı yarıya bile yapmıyor mu?

Yeniden tanımlamaya veya "standart dışı" yuvarlamaya dikkat edin ...

(Ayrıca bkz. Https://stackoverflow.com/a/33019948/109839 )


2
Bu cevap biraz belirsiz. Round half to evenkesinlikle IEEE 754 tarafından reçete edilmez, bunun yerine birkaç yuvarlama seçeneğinden sadece biridir standart tarafından açıklanan . Round to nearest, ties away from zero(yani çoğu insanın beklediği davranış) da bir seçenektir ve örneğin C / C ++ 'da varsayılan seçenektir.
tel

Katılıyorum, ifadeler oldukça kafa karıştırıcı. Ben Python (sonundaki tabloya bakınız Heven yarısını yakalanması olduğunu anlamına geliyordu ne docs.python.org/3.7/library/...round reçete edilir açıklanmıştır) ve "hatta yuvarlak yarım" şekline göre böylece yapıyor standart ile çalışmak (veya tanımlamak).
Mapio

8

Ayrıca python3.x kullanıyorsanız numpy komutunu da kullanabilirsiniz.

import numpy as np
x = 2.3
print(np.rint(x))
>>> 2.0

7

Çözümünüz ikinci argümanı (ondalık basamak sayısı) belirtmeden dolaşıyor

>>> round(0.44)
0
>>> round(0.64)
1

ki bu çok daha iyi bir sonuçtur

>>> int(round(0.44, 2))
0
>>> int(round(0.64, 2))
0

Adresindeki Python belgelerinden Https://docs.python.org/3/library/functions.html#round adresindeki

yuvarlak (sayı [, rakamlar])

Ondalık noktadan sonra rakamın hassasiyetine yuvarlanan dönüş sayısı. Ndigits atlanırsa veya Yok ise, girişine en yakın tamsayıyı döndürür.

Not

Şamandıralar için round () davranışı şaşırtıcı olabilir: örneğin, round (2.675, 2) beklenen 2.68 yerine 2.67 verir. Bu bir hata değildir: ondalık kesirlerin çoğunun tam olarak bir şamandıra olarak temsil edilememesi sonucudur. Daha fazla bilgi için bkz. Kayan Nokta Aritmetiği: Sorunlar ve Sınırlamalar.


1

A için iki haneli bir yaklaşıma ihtiyacınız varsa (örneğin), int(A*100+0.5)/100.0 , aradığınızı yaparsınız.

Üç basamaklı bir yaklaşıma ihtiyacınız varsa çarpın ve 1000'e bölün ve bu şekilde devam edin.


1

Bunun gibi bir şey de çalışmalı

import numpy as np    

def proper_round(a):
    '''
    given any real number 'a' returns an integer closest to 'a'
    '''
    a_ceil = np.ceil(a)
    a_floor = np.floor(a)
    if np.abs(a_ceil - a) < np.abs(a_floor - a):
        return int(a_ceil)
    else:
        return int(a_floor)

0

Bu amaçla sadece aşağıdakileri yapmanızı öneririm -

int(round(x))

Bu size en yakın tamsayıyı verecektir.

Bu yardımcı olur umarım!!


0

Aşağıdaki çözümü kullanıyorum ve önerebilirim (python3.6):

y = int(x + (x % (1 if x >= 0 else -1)))

Yarı sayılar (pozitifler ve negatifler) için iyi çalışır ve int'den (yuvarlak (x)) daha da hızlı çalışır:

round_methods = [lambda x: int(round(x)), 
                 lambda x: int(x + (x % (1 if x >= 0 else -1))),
                 lambda x: np.rint(x).astype(int),
                 lambda x: int(proper_round(x))]

for rm in round_methods:
    %timeit rm(112.5)
Out:
201 ns ± 3.96 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
159 ns ± 0.646 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
925 ns ± 7.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
1.18 µs ± 8.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

for rm in round_methods:
    print(rm(112.4), rm(112.5), rm(112.6))
    print(rm(-12.4), rm(-12.5), rm(-12.6))
    print('=' * 11)

Out:
112 112 113
-12 -12 -13
===========
112 113 113
-12 -13 -13
===========
112 112 113
-12 -12 -13
===========
112 113 113
-12 -13 -13
===========
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.