Membulatkan ke 5 (atau nomor lain) dengan Python

162

Apakah ada fungsi bawaan yang dapat membulatkan seperti berikut?

10 -> 10
12 -> 10
13 -> 15
14 -> 15
16 -> 15
18 -> 20
Pydev UA
sumber

Jawaban:

304

Saya tidak tahu fungsi standar dengan Python, tetapi ini berfungsi untuk saya:

Python 2

def myround(x, base=5):
    return int(base * round(float(x)/base))

Python3

def myround(x, base=5):
    return base * round(x/base)

Sangat mudah untuk melihat mengapa hal di atas berhasil. Anda ingin memastikan bahwa angka Anda dibagi 5 adalah bilangan bulat, dibulatkan dengan benar. Jadi, pertama-tama kita melakukan hal itu (di round(float(x)/5)mana floathanya diperlukan di Python2), dan kemudian karena kita dibagi 5, kita kalikan dengan 5 juga. Konversi terakhir ke intadalah karena round()mengembalikan nilai floating-point dalam Python 2.

Saya membuat fungsi lebih umum dengan memberinya baseparameter, default ke 5.

Alok Singhal
sumber
3
Jika hanya bilangan bulat dan pembulatan ke bawah, maka Anda juga bisa melakukannyax // base * base
Tjorriemorrie
7
ini saya menjadi paranoid tetapi saya lebih suka menggunakan floor()dan ceil()bukannya casting:base * floor(x/base)
user666412
1
@ user666412 math.floordan math.ceiljangan izinkan digunakan dengan basis kustom, sehingga preferensi tidak relevan.
Acumenus
48

Untuk pembulatan ke nilai non-integer, seperti 0,05:

def myround(x, prec=2, base=.05):
  return round(base * round(float(x)/base),prec)

Saya menemukan ini berguna karena saya hanya bisa melakukan pencarian dan mengganti kode saya untuk mengubah "round (" menjadi "myround (", tanpa harus mengubah nilai parameter.

CCKx
sumber
2
Anda dapat menggunakan: def my_round(x, prec=2, base=0.05): return (base * (np.array(x) / base).round()).round(prec) yang menerima array numpy juga.
saubhik
23

Ini hanya masalah penskalaan

>>> a=[10,11,12,13,14,15,16,17,18,19,20]
>>> for b in a:
...     int(round(b/5.0)*5.0)
... 
10
10
10
15
15
15
15
15
20
20
20
amo-ej1
sumber
14

Menghapus 'sisanya' akan bekerja:

rounded = int(val) - int(val) % 5

Jika nilainya diberikan integer:

rounded = val - val % 5

Sebagai fungsi:

def roundint(value, base=5):
    return int(value) - int(value) % int(base)
hgdeoro
sumber
Saya suka jawaban ini untuk pembulatan ke nilai pecahan terdekat. yaitu Jika saya hanya ingin kenaikan 0,25.
kacang jersey
14
def round_to_next5(n):
    return n + (5 - n) % 5
Andy Wong
sumber
9

round (x [, n]): nilai dibulatkan ke kelipatan terdekat dari 10 ke minus daya n. Jadi jika n negatif ...

def round5(x):
    return int(round(x*2, -1)) / 2

Karena 10 = 5 * 2, Anda dapat menggunakan pembagian integer dan perkalian dengan 2, daripada pembagian float dan perkalian dengan 5.0. Bukan berarti itu penting, kecuali jika Anda suka sedikit bergeser

def round5(x):
    return int(round(x << 1, -1)) >> 1
pwdyson
sumber
1
+1 untuk menunjukkan kepada kami bahwa round () dapat menangani pembulatan ke kelipatan selain 1.0, termasuk nilai yang lebih tinggi. (Namun, perlu dicatat bahwa pendekatan bit-shifting tidak akan berfungsi dengan float, belum lagi itu jauh lebih mudah dibaca oleh sebagian besar programmer.)
Peter Hansen
1
@Peter Hansen terima kasih untuk +1nya. Perlu memiliki int (x) untuk pengalihan bit agar bekerja dengan float. Setuju bukan yang paling mudah dibaca dan saya tidak akan menggunakannya sendiri, tapi saya suka "kemurnian" itu hanya melibatkan 1 dan bukan 2 atau 5.
pwdyson
6

Maaf, saya ingin mengomentari jawaban Alok Singhai, tetapi itu tidak akan membiarkan saya karena kurangnya reputasi = /

Bagaimanapun, kita dapat menggeneralisasi satu langkah lagi dan pergi:

def myround(x, base=5):
    return base * round(float(x) / base)

Ini memungkinkan kita untuk menggunakan basis non-integer, seperti .25atau basis fraksional lainnya.

ArturJ
sumber
Tolong jangan mencoba melewati batasan pengguna baru dengan memposting komentar sebagai jawaban. Pembatasan ada karena suatu alasan . Pertimbangkan ini sebagai alasan yang memungkinkan mengapa dan bagaimana beberapa jawaban dihapus?
Selamat tinggal StackExchange
4

Versi modifikasi divround :-)

def divround(value, step, barrage):
    result, rest = divmod(value, step)
    return result*step if rest < barrage else (result+1)*step
Christian Hausknecht
sumber
jadi dalam hal ini Anda menggunakan divround (nilai, 5, 3)? atau mungkin divround (nilai, 5, 2.5)?
pwdyson
divround (nilai, 5, 3), tepatnya.
Christian Hausknecht
4

Menggunakan:

>>> def round_to_nearest(n, m):
        r = n % m
        return n + m - r if r + r >= m else n - r

Itu tidak menggunakan perkalian dan tidak akan mengkonversi dari / ke mengapung.

Pembulatan ke kelipatan 10 terdekat:

>>> for n in range(-21, 30, 3): print('{:3d}  =>  {:3d}'.format(n, round_to_nearest(n, 10)))
-21  =>  -20
-18  =>  -20
-15  =>  -10
-12  =>  -10
 -9  =>  -10
 -6  =>  -10
 -3  =>    0
  0  =>    0
  3  =>    0
  6  =>   10
  9  =>   10
 12  =>   10
 15  =>   20
 18  =>   20
 21  =>   20
 24  =>   20
 27  =>   30

Seperti yang Anda lihat, ini berfungsi baik untuk angka negatif maupun positif. Dasi (mis. -15 dan 15) akan selalu dibulatkan ke atas.

Contoh serupa yang membulatkan ke kelipatan 5 terdekat, menunjukkan bahwa ia juga berperilaku seperti yang diharapkan untuk "pangkalan" yang berbeda:

>>> for n in range(-21, 30, 3): print('{:3d}  =>  {:3d}'.format(n, round_to_nearest(n, 5)))
-21  =>  -20
-18  =>  -20
-15  =>  -15
-12  =>  -10
 -9  =>  -10
 -6  =>   -5
 -3  =>   -5
  0  =>    0
  3  =>    5
  6  =>    5
  9  =>   10
 12  =>   10
 15  =>   15
 18  =>   20
 21  =>   20
 24  =>   25
 27  =>   25
Wouter Bolsterlee
sumber
2

Jika seseorang membutuhkan "pembulatan keuangan" (0,5 putaran selalu naik):

def myround(x, base=5):
    roundcontext = decimal.Context(rounding=decimal.ROUND_HALF_UP)
    decimal.setcontext(roundcontext)
    return int(base *float(decimal.Decimal(x/base).quantize(decimal.Decimal('0'))))

Sesuai dokumentasi, opsi pembulatan lainnya adalah:

ROUND_CEILING (menuju Infinity),
ROUND_DOWN (menuju nol),
ROUND_FLOOR (menuju -Infinity),
ROUND_HALF_DOWN (ke yang terdekat dengan ikatan menuju nol),
ROUND_HALF_EVEN (ke orang terdekat dengan ikatan pergi ke bilangan bulat terdekat),
ROUND_HALF_UP (kepada orang terdekat dengan ikatan yang terjadi dengan ikatan terdekat) jauh dari nol), atau
ROUND_UP (jauh dari nol).
ROUND_05UP (jauh dari nol jika digit terakhir setelah pembulatan ke nol adalah 0 atau 5; sebaliknya menuju nol)

Secara default Python menggunakan ROUND_HALF_EVEN karena memiliki beberapa keunggulan statistik (hasil yang dibulatkan tidak bias).

Piotr Siejda
sumber
2

Untuk bilangan bulat dan dengan Python 3:

def divround_down(value, step):
    return value//step*step


def divround_up(value, step):
    return (value+step-1)//step*step

Memproduksi:

>>> [divround_down(x,5) for x in range(20)]
[0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 15, 15, 15, 15, 15]
>>> [divround_up(x,5) for x in range(20)]
[0, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 15, 15, 15, 15, 15, 20, 20, 20, 20]
Sylvain Leroux
sumber
1

Kelipatan 5 berikutnya

Pertimbangkan 51 yang perlu dikonversi menjadi 55:

code here

mark = 51;
r = 100 - mark;
a = r%5;
new_mark = mark + a;
vijay
sumber
1

Ini kode C saya. Jika saya memahaminya dengan benar, itu seharusnya menjadi sesuatu seperti ini;

#include <stdio.h>

int main(){
int number;

printf("Enter number: \n");
scanf("%d" , &number);

if(number%5 == 0)
    printf("It is multiple of 5\n");
else{
    while(number%5 != 0)
        number++;
  printf("%d\n",number);
  }
}

dan ini juga membulatkan ke kelipatan 5 terdekat bukan hanya mengumpulkan;

#include <stdio.h>

int main(){
int number;

printf("Enter number: \n");
scanf("%d" , &number);

if(number%5 == 0)
    printf("It is multiple of 5\n");
else{
    while(number%5 != 0)
        if (number%5 < 3)
            number--;
        else
        number++;
  printf("nearest multiple of 5 is: %d\n",number);
  }
}
Ege Merey
sumber
1

Cara lain untuk melakukan ini (tanpa operator multiplikasi atau divisi eksplisit):

def rnd(x, b=5):
    return round(x + min(-(x % b), b - (x % b), key=abs))
cosmic_inquiry
sumber
-3

Anda dapat “menipu” int()untuk membulatkan alih-alih membulatkannya dengan menambahkan 0.5nomor yang Anda lewati int().

Franciska Zsiros
sumber
2
Ini sebenarnya tidak menjawab pertanyaan
Uri Agassi