Semua ku 
berjanggut , kawan!
Kita semua tahu apa itu pembulatan. Jika seseorang lupa, maka pembulatan adalah penggantian angka dengan nilai perkiraannya, ditulis dengan digit signifikan lebih sedikit. Jika Anda bertanya pada seseorang dengan cepat apa yang terjadi ketika Anda membulatkan 6,5 ke bilangan bulat, ia akan menjawab "7" tanpa ragu-ragu. Kami telah diajarkan dari sekolah bahwa angka dibulatkan ke bilangan bulat terdekat, yang nilainya lebih besar. Yaitu, jika dalam bilangan bulat bagian pecahan sama dengan atau lebih dari setengah pembuangan seluruh bagian, maka kami membulatkan bilangan asli ke bilangan terbesar terdekat.
Sederhananya:
6,4 = 6 6,5 = 7 6,6 = 7 
dll.
Maka, meninggalkan sekolah dan menjadi programmer, kita sering mengharapkan perilaku yang sama dari bahasa pemrograman kita yang kuat. Melupakan sepenuhnya bahwa di sekolah kita diajarkan “pembulatan matematis”, tetapi sebenarnya ada lebih banyak jenis pembulatan. Di Wikipedia saja, 
Anda dapat menggali berapa banyak opsi pembulatan 0,5 ke bilangan bulat terdekat:
- Pembulatan matematika
- Pembulatan acak
- Pembulatan bergantian
- Pembulatan bank
Jenis pertama, "pembulatan matematika," kita semua belajar dari sekolah. Anda dapat membaca tentang tipe kedua dan ketiga di waktu luang Anda, mereka tidak menarik bagi saya dalam artikel ini hari ini.
Tapi "pembulatan perbankan" sudah menarik. "Kenapa?" - kamu bertanya. Di subnet kita sering menggunakan kelas 
Konversi , yang menyediakan banyak metode untuk mengkonversi satu tipe data ke yang lain (tidak menjadi bingung dengan para pemain, itu akan dijelaskan di bawah). Dan sekarang, ternyata ketika mengubah angka floating-point ( 
dobel, float, desimal ) menjadi tipe 
int integer melalui metode 
Convert.ToInt32, pembulatan “perbankan” bekerja di bawah tenda. Ini digunakan di sini secara default!
Dan sepertinya ketidaktahuan tentang hal sepele ini tidak terlalu memengaruhi pekerjaan Anda, tetapi segera setelah Anda harus bekerja dengan statistik dan menghitung indikator berdasarkan sekelompok semua jenis catatan dan angka hal ini akan keluar ke samping. Karena kami berharap (dari ketidaktahuan) bahwa semua konversi / pembulatan kami dalam perhitungan akan bekerja sesuai dengan aturan pembulatan "matematika". Dan kita terlihat seperti seekor domba jantan di gerbang baru untuk hasil pembulatan 
6.5 , yaitu 
6 .
Pikiran pertama dari programmer yang melihat ini adalah: "Mungkin pembulatan bekerja pada arah yang berlawanan, dan menurut aturan itu membulatkan ke angka terkecil?", "Mungkin aku lupa sesuatu dari matematika sekolah?". Kemudian dia pergi ke google dan memahami bahwa mereka tidak melupakan apa pun, dan bahwa beberapa jenis massa sedang terjadi. Pada langkah ini, pengembang malas akan memutuskan bahwa ini adalah perilaku standar metode 
Convert.ToInt32 , bulat ke bilangan bulat terkecil, dan skor untuk pencarian lebih lanjut. Dan dia akan berpikir bahwa jika 
Convert.ToInt32 (6,5) = 
6 , maka dengan analogi 
Convert.ToInt32 (7,5) = 
7 . Tapi itu dia. Di masa depan, pengembang tersebut akan dipukul dengan sekelompok bug dari departemen QA.
Faktanya adalah pembulatan “perbankan” bekerja sedikit lebih rumit - pembulatan angka ke bilangan bulat genap terdekat, dan bukan ke modulo bilangan bulat terdekat. Jenis pembulatan ini seharusnya lebih jujur jika diterapkan dalam operasi perbankan - bank tidak akan mencabut diri mereka sendiri atau klien, dengan asumsi bahwa ada banyak operasi dengan bagian bilangan bulat genap seperti halnya ada operasi dengan bagian bilangan bulat ganjil. Tetapi bagi saya - masih belum jelas :) Jadi itu sebabnya 
Convert.ToInt32 (6.5) akan memberikan hasil 
6 , dan hasil untuk 
Convert.ToInt32 (7.5) akan menjadi 
8 , bukan 7 :)
Apa yang harus dilakukan untuk membuat pembulatan "matematis" yang akrab bagi semua orang? Metode 
konversi kelas tidak memiliki opsi pembulatan tambahan. Memang benar, karena kelas ini berfungsi terutama bukan untuk pembulatan, tetapi untuk konversi tipe. Kelas 
Matematika yang luar biasa dengan metode 
Putarannya datang untuk menyelamatkan. Tapi di sini juga hati-hati, karena secara default metode ini berfungsi sama dengan pembulatan di 
Convert.ToInt32 () - sesuai dengan aturan "perbankan". Namun, perilaku ini dapat diubah menggunakan argumen kedua, yang merupakan bagian dari metode 
Round . Jadi, 
Math.Round (someNumber, MidpointRounding.ToEven ) akan memberi kita pembulatan "perbankan" default. Tapi 
Math.Round (someNumber, MidpointRounding.AwayFromZero ) akan bekerja sesuai dengan aturan pembulatan "matematika" yang biasa.
Dan omong-omong, 
Convert.ToInt32 () tidak menggunakan 
System.Math.Round () di bawah tenda. Khusus menggali 
implementasi metode ini pada pembulatan github dianggap sesuai dengan residu:
 public static int ToInt32(double value) { if (value >= 0) { if (value < 2147483647.5) { int result = (int)value; double dif = value - result; if (dif > 0.5 || dif == 0.5 && (result & 1) != 0) result++; return result; } } else { if (value >= -2147483648.5) { int result = (int)value; double dif = value - result; if (dif < -0.5 || dif == -0.5 && (result & 1) != 0) result--; return result; } } throw new OverflowException(Environment.GetResourceString("Overflow_Int32")); } 
Dan akhirnya, beberapa kata tentang 
tipe casting :
 var number = 6.9; var intNumber = (int)number; 
Dalam contoh ini, saya melemparkan tipe floating point ( 
ganda dalam hal ini) ke integer 
int . Jadi, ketika casting ke tipe integer, seluruh bagian non-integer 
terpotong . Dengan demikian, dalam contoh ini, variabel " 
intNumber " akan 
berisi angka 
6 . Tidak ada aturan pembulatan di sini, hanya memotong semua yang muncul setelah titik desimal. Ingat ini!
Tautan terkait:
PS Terima kasih kepada Maxim Yakushkin untuk menarik perhatian pada momen implisit ini.
Omong-omong, dalam 
python, pembulatan secara default bekerja dengan cara yang sama pada basis "perbankan". Mungkin hal yang sama dalam bahasa Anda, hati-hati dengan angka :)