Bagaimana cara mengkonversi desimal ke int di C #?

227

Bagaimana cara mengonversi desimal ke int?

Rob Hruska
sumber
11
Akan sangat membantu untuk mengetahui apakah Anda ingin membulatkan ke int terdekat atau hanya menjatuhkan angka setelah desimal (yaitu: selalu bulat ke bawah)
Dinah
128
sejujurnya saya tidak mengerti gunanya menolak pertanyaan yang sebenarnya. ya, jawabannya dapat ditemukan di google TAPI bukankah itu hanya meningkatkan kualitas situs jika orang berhenti menutup setiap pertanyaan kedua? itu bukan seperti pertanyaan ini adalah spam atau apa pun, dan aku yakin itu akan bermanfaat bagi banyak pendatang baru untuk c #
jay_t55

Jawaban:

268

Gunakan Convert.ToInt32mulai dari mscorlibpada

decimal value = 3.14m;
int n = Convert.ToInt32(value);

Lihat MSDN . Anda juga bisa menggunakan Decimal.ToInt32. Sekali lagi, lihat MSDN . Akhirnya, Anda dapat melakukan pemeran langsung seperti pada

decimal value = 3.14m;
int n = (int) value;

yang menggunakan operator pemeran eksplisit. Lihat MSDN .

jason
sumber
10
Awas: Konversi memiliki beberapa perilaku mengejutkan untuk konversi tertentu ( nullvs 0vs. ""). Saya akan merekomendasikan untuk tidak pernah menggunakan Konversi kecuali Anda benar-benar membutuhkan fleksibilitasnya (yaitu dalam skenario yang diketik secara dinamis)
Eamon Nerbonne
1
-1 karena ini tidak akan bekerja untuk nilai-nilai seperti desimal.MaxValue dan desimal.MinValue dan menghasilkan OverflowException. Saya percaya bahwa @Will akan memberikan jawaban yang lebih baik di sini stackoverflow.com/a/501165/39532
mezoid
8
Hati-hati, karena Convert.ToInt32dan Decimal.ToInt32berperilaku berbeda. Dari MSDN: Decimal.ToInt32- Nilai kembali adalah bagian integral dari nilai desimal; digit fraksional terpotong . Convert.ToInt32- Nilai pengembalian dibulatkan ke bilangan bulat bertanda 32-bit terdekat. Jika nilainya setengah di antara dua bilangan bulat, bilangan genap dikembalikan; yaitu, 4,5 dikonversi menjadi 4, dan 5,5 dikonversi menjadi 6.
vezucci
67

Kamu tidak bisa

Yah, tentu saja Anda bisa , namun int (System.Int32) tidak cukup besar untuk menampung setiap kemungkinan nilai desimal.

Itu berarti jika Anda membuat desimal yang lebih besar dari int.MaxValue Anda akan overflow, dan jika desimal lebih kecil dari int.MinValue, itu akan underflow.

Apa yang terjadi ketika Anda under / overflow? Satu dari dua hal. Jika build Anda tidak dicentang (yaitu, CLR tidak peduli jika Anda melakukannya), aplikasi Anda akan berlanjut setelah nilai over / underflow, tetapi nilai di int tidak akan seperti yang Anda harapkan. Ini dapat menyebabkan bug yang terputus-putus dan mungkin sulit untuk diperbaiki. Anda akan berakhir aplikasi Anda dalam keadaan yang tidak diketahui yang dapat mengakibatkan aplikasi Anda merusak data penting apa pun yang sedang bekerja. Tidak baik.

Jika rakitan Anda dicentang (properties-> build-> advanced-> periksa aritmatika overflow / underflow atau opsi / checked compiler), kode Anda akan melempar pengecualian ketika terjadi under / overflow. Ini mungkin lebih baik daripada tidak; Namun standar untuk rakitan adalah tidak memeriksa over / underflow.

Pertanyaan sebenarnya adalah "apa yang Anda coba lakukan?" Tanpa mengetahui persyaratan Anda, tidak ada yang bisa memberi tahu Anda apa yang harus Anda lakukan dalam kasus ini, selain yang sudah jelas: JANGAN MELAKUKANNYA.

Jika Anda secara khusus TIDAK peduli, jawaban di sini valid. Namun, Anda harus mengomunikasikan pemahaman Anda bahwa overflow dapat terjadi dan itu tidak masalah dengan membungkus kode cor Anda di blok yang tidak dicentang

unchecked
{
  // do your conversions that may underflow/overflow here
}

Dengan begitu orang-orang yang datang di belakang Anda memahami bahwa Anda tidak peduli, dan jika di masa depan seseorang mengubah bangunan Anda ke / diperiksa, kode Anda tidak akan rusak secara tak terduga.

Jika semua yang ingin Anda lakukan adalah menjatuhkan bagian fraksional dari angka tersebut, meninggalkan bagian integral, Anda dapat menggunakan Math.Truncate.

decimal actual = 10.5M;
decimal expected = 10M;
Assert.AreEqual(expected, Math.Truncate(actual));

sumber
3
Meskipun saya menduga mereka adalah hal yang sama di bawah tenda jika inputnya adalah desimal, saya merasa lebih nyaman menggunakan Desimal. Lebih singkat daripada Matematika. yang bukan basis 10, sebagai lawan dari Desimal. Truncate, yang merupakan pemotongan benar dari nomor basis 10.
Brian
7
Konteks yang tidak diperiksa tidak berlaku untuk desimal; operasi pada desimal akan menghasilkan OverflowExceptions.
Dave
46
int i = (int)d;

akan memberi Anda nomor dibulatkan.

Jika Anda ingin membulatkan ke nomor genap terdekat (yaitu> .5 akan mengumpulkan), Anda dapat menggunakan

int i = (int)Math.Round(d, MidpointRounding.ToEven);

Secara umum Anda dapat memilih antara semua tipe numerik dalam C #. Jika tidak ada informasi yang akan hilang selama pemeran, Anda dapat melakukannya secara implisit:

int i = 10;
decimal d = i;

meskipun Anda masih dapat melakukannya secara eksplisit jika Anda menginginkan:

int i = 10;
decimal d = (decimal)i;

Namun, jika Anda akan kehilangan informasi melalui para pemain, Anda harus melakukannya secara eksplisit (untuk menunjukkan bahwa Anda sadar Anda mungkin kehilangan informasi):

decimal d = 10.5M;
int i = (int)d;

Di sini Anda kehilangan "0,5". Ini mungkin baik-baik saja, tetapi Anda harus eksplisit tentang hal itu dan membuat pemeran eksplisit untuk menunjukkan Anda tahu Anda mungkin kehilangan informasi.

ICR
sumber
1
Anda benar-benar ingin MidpointRounding.AwayFromZero jika Anda ingin> * .5 selalu berdasarkan pada pengalaman saya mencoba kode di atas melihat sampel output di sini: msdn.microsoft.com/en-us/library/…
Elijah Lofgren
@ElijahLofgren Agak tergantung: Jika Anda melakukan statistik, ToEvenharus mencegah penyimpangan statistik. Namun jika Anda beroperasi dengan barang atau uang yang dikenakan biaya, AwayFromZerosepertinya pilihan yang tepat.
mbx
22
decimal d = 2;
int i = (int) d;

Ini seharusnya bekerja dengan baik.

luiscubal
sumber
Hati-hati, dengan informasi konversi eksplisit mungkin hilang.
Phaedrus
21
Ketika mengkonversi dari desimal ke int, informasi akan selalu hilang tetapi saya yakin itulah intinya.
Dinah
8

System.Decimalmengimplementasikan IConvertableantarmuka, yang memiliki ToInt32()anggota.

Apakah menelepon System.Decimal.ToInt32()bekerja untuk Anda?

Andy
sumber
2
Dari dokumentasi : "API ini mendukung infrastruktur .NET Framework dan tidak dimaksudkan untuk digunakan langsung dari kode Anda". Mengapa tidak menggunakan Convert.ToInt32?
H.Wolper
7

Trik yang rapi untuk pembulatan cepat adalah dengan menambahkan 0,5 sebelum Anda memasukkan desimal ke int.

decimal d = 10.1m;
d += .5m;
int i = (int)d;

Masih pergi i=10, tapi

decimal d = 10.5m;
d += .5m;
int i = (int)d;

Akan mengumpulkan sehingga i=11.

DeadlyBrad42
sumber
5
Mengapa repot-repot melakukan ini ketika ada Math.Floor dan Math.Ceiling?
Badaro
Pada saat itu, saya cukup baru untuk C # dan untuk beberapa alasan saya tidak menyadari fungsi-fungsi ini ada. Sebenarnya ini adalah trik yang saya pelajari dari C / C ++, yang ternyata lebih bermanfaat.
DeadlyBrad42
1
Bagaimana jika nilai desimalnya adalah -9,3?
supercat
6

Saya lebih suka menggunakan Math.round , Math.floor , Math.Ceiling atau Math.Truncate secara eksplisit mengatur mode pembulatan yang sesuai.

Perhatikan bahwa mereka semua juga mengembalikan Desimal - karena Desimal memiliki rentang nilai yang lebih besar daripada Int32, jadi Anda masih perlu melakukan pengecoran (dan periksa apakah ada overflow / underflow).

 checked {
   int i = (int)Math.Floor(d);
 }
Mark Brackett
sumber
6

desimal d = 5.5;

int i = decimal.ToInt32(d);// you will get i = 5

ref: tautan teks

axel22
sumber
6

Membulatkan desimal ke bilangan bulat terdekat

decimal a ;
int b = (int)(a + 0.5m);

kapan a = 49.9, lalub = 50

kapan a = 49.5, lalub = 50

kapan a = 49.4, lalu b = 49dll.

sleepwalkerfx
sumber
0

Saya menemukan bahwa operator casting tidak bekerja jika Anda memiliki desimal kotak (yaitu nilai desimal di dalam jenis objek). Convert.ToInt32 (desimal sebagai objek) berfungsi dengan baik dalam kasus ini.

Situasi ini muncul ketika mengambil nilai IDENTITY / AUTONUMBER dari database:

SqlCommand foo = new SqlCommand("INSERT INTO...; SELECT SCOPE_IDENTITY()", conn);
int ID = Convert.ToInt32(foo.ExecuteScalar());  // works
int ID = (int)foo.ExecuteScalar();              // throws InvalidCastException

Lihat 4.3.2 Konversi unboxing

Timbo
sumber
2
Menambahkan lebih banyak untuk referensi: itu karena Anda hanya dapat membuka kotak ke jenis asli yang sama. Di sini SELECT SCOPE_IDENTITY()mengembalikan numeric(38, 0)yang diterjemahkan decimaloleh .NET. foo.ExecuteScalar()mengembalikan decimalkotak objectyang tidak dapat dicor langsung ke int. (int)(decimal)foo.ExecuteScalar()atau Convert.ToInt32(foo.ExecuteScalar())akan bekerja.
rageit
0

Tampaknya tidak ada jawaban yang berhubungan dengan OverflowException / UnderflowException yang berasal dari upaya mengubah desimal yang berada di luar kisaran int.

int intValue = (int)Math.Max(int.MinValue, Math.Min(int.MaxValue, decimalValue));

Solusi ini akan mengembalikan nilai int maksimum atau minimum yang mungkin jika nilai desimal berada di luar kisaran int. Anda mungkin ingin menambahkan beberapa pembulatan dengan Math.Round, Math.Ceiling atau Math.Floor ketika nilai berada di dalam kisaran int.

Kapten-N
sumber