Cara terbaik untuk mendapatkan bagian bilangan bulat dari bilangan Desimal

91

Apa cara terbaik untuk mengembalikan seluruh bagian bilangan desimal (dalam c #)? (Ini harus bekerja untuk bilangan yang sangat besar yang mungkin tidak cocok dengan int).

GetIntPart(343564564.4342) >> 343564564
GetIntPart(-323489.32) >> -323489
GetIntPart(324) >> 324

Tujuan dari ini adalah: Saya memasukkan ke dalam bidang desimal (30,4) di db, dan ingin memastikan bahwa saya tidak mencoba memasukkan angka yang terlalu panjang untuk bidang tersebut. Menentukan panjang bagian bilangan bulat dari desimal adalah bagian dari operasi ini.

Yaakov Ellis
sumber
Anda tidak bisa mendapatkan bagian int; Anda bisa mendapatkan bagian bilangan bulat dan membuang bagian pecahan. Seluruh bagian angka dari Desimal dapat dengan mudah meluap int dan baik melempar atau membungkus, diam-diam membunuh kode Anda.
1
Nah, itulah mengapa pertanyaan ini tidak sesederhana kelihatannya. Saya membutuhkan ini untuk bekerja untuk jumlah yang sangat besar dan dapat diandalkan seperti halnya untuk jumlah kecil. Namun, "bilangan bulat" lebih akurat daripada "int" - saya akan mengulanginya di atas.
Yaakov Ellis

Jawaban:

215

Ngomong-ngomong, (int) Decimal.MaxValue akan meluap. Anda tidak bisa mendapatkan bagian "int" dari desimal karena desimalnya terlalu besar untuk dimasukkan ke dalam kotak int. Baru saja memeriksa ... bahkan terlalu besar untuk waktu yang lama (Int64).

Jika Anda ingin sedikit nilai Desimal di sebelah KIRI titik, Anda perlu melakukan ini:

Math.Truncate(number)

dan mengembalikan nilai sebagai ... SEBUAH DESIMAL atau GANDA.

edit: Truncate jelas merupakan fungsi yang benar!


sumber
Jadi hasilnya adalah desimal atau ganda yang tidak akan pernah memiliki apa-apa setelah titik tetapi tidak ada objek bawaan untuk menyimpan hasilnya sebagai "int" (tanpa tempat desimal) yang tampaknya agak timpang?
Coops
@CodeBlend: Tidak banyak panggilan untuk mendesain kerangka kerja seputar keinginan untuk kehilangan presisi.
@ CodeBlend: Anda masih akan kehilangan presisi karena Anda memotong nilai desimal sebuah angka. Tidak yakin apa yang Anda maksud.
Tidak yakin ini akan berhasil atau tidak. Karena Math.Truncate (-5.99999999999999999) mengembalikan -6.0 untuk saya ... !!
Bharat Mori
@Bharat Mori: Tampaknya -5.99999999999999999 dibulatkan menjadi -6.0 sebelum pemotongan. Coba dengan sufiks "m" dan itu akan berhasil. Math.Truncate (-5.99999999999999999m) menghasilkan -5.
Henry
23

Saya pikir System.Math.Truncate adalah apa yang Anda cari.

Mark Carpenter
sumber
4

Tergantung pada apa yang Anda lakukan.

Misalnya:

//bankers' rounding - midpoint goes to nearest even
GetIntPart(2.5) >> 2
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -6

atau

//arithmetic rounding - midpoint goes away from zero
GetIntPart(2.5) >> 3
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -7

Defaultnya selalu yang pertama, yang bisa menjadi kejutan tetapi sangat masuk akal .

Pemeran eksplisit Anda akan melakukan:

int intPart = (int)343564564.5
// intPart will be 343564564

int intPart = (int)343564565.5
// intPart will be 343564566

Dari cara Anda mengucapkan pertanyaan, sepertinya ini bukan yang Anda inginkan - Anda ingin melontarkannya setiap saat.

Saya akan melakukan:

Math.Floor(Math.Abs(number));

Periksa juga ukurannya decimal- ukurannya bisa sangat besar, jadi Anda mungkin perlu menggunakan file long.

Keith
sumber
(panjang) Decimal.MaxValue meluap.
Poin yang adil - Saya rasa itulah mengapa Math.Truncate (desimal) mengembalikan desimal.
Keith
Di C #, casting ke int tidak bulat, jadi (int) 0.6f akan menjadi 0, dan (int) 343564565.5 akan diakhiri dengan 5, bukan 6. Coba di sini: repl.it/repls/LuxuriousCheerfulDistributeddatabase
sschmidTU
0

Anda hanya perlu mentransmisikannya, seperti:

int intPart = (int)343564564.4342

Jika Anda masih ingin menggunakannya sebagai desimal dalam perhitungan selanjutnya, maka Math.Truncate (atau mungkin Math.Floor jika Anda menginginkan perilaku tertentu untuk bilangan negatif) adalah fungsi yang Anda inginkan.

Noldorin
sumber
5
Ini salah salah salah. Jika hasilnya lebih besar dari apa yang bisa ditahan Int32, itu akan memunculkan pengecualian atau (bahkan lebih buruk !!!) secara diam-diam meluap dan membungkus kembali, memberi Anda hasil yang sepenuhnya salah tanpa Anda menyadarinya.
2
Tidak, itu tidak salah . Banyak yang tidak valid untuk desimal / nilai floating point yang sangat besar, tetapi tidak masalah untuk sebagian besar situasi. Angka sangat sering dibatasi menjadi cukup rendah saat melakukan pengkodean, jadi ini tidak perlu menjadi masalah. Juga, saya menyediakan solusi Math.Truncate yang berfungsi untuk semua nilai.
Noldorin
2
Saya mengerti mengapa Anda marah pada saya. Faktanya adalah jawaban Anda salah. Anda menyuruhnya untuk mengambil risiko agar tidak rusak karena, hei, banyak angka kecil. Itu adalah resiko yang bodoh untuk diambil. Anda harus mengedit jawaban Anda dan menghapus semuanya kecuali Matematika. Potong sebagai satu-satunya bagian yang benar.
1
Anda tahu apa yang mereka katakan tentang ASSUME. Selain itu, asumsi Anda sangat buruk. Apakah itu peradangan? Saya kira Anda bisa mengatakan itu. Anda juga dapat mengatakan bahwa mengatakan kepada seseorang untuk melakukan sesuatu yang bodoh yang akan menyebabkan masalah bagi mereka di kemudian hari juga bersifat menghasut, jika tidak benar-benar tidak etis.
1
Memang itu salah jika saya bermaksud memberikan jawaban yang menyesatkan. Seolah-olah, saya hanya mencoba membantu. Jika saya bersalah karena sedikit kesalahpahaman atau tidak sepenuhnya menghargai pertanyaan itu, itu cukup adil - itu bukan kejahatan. Jadi mengapa kita berdebat sekarang? Kami semua setuju bahwa Truncate adalah jawaban yang tepat.
Noldorin
0

Cara yang sangat mudah untuk memisahkan nilai dan nilai bagian pecahannya.

double  d = 3.5;
int i = (int)d;
string s = d.ToString();
s = s.Replace(i + ".", "");

s adalah pecahan bagian = 5 dan
i adalah nilai sebagai integer = 3

Amit Gohel
sumber
1
Lihat jawaban teratas di atas. Ini tidak berhasil karena (int)Decimal.MaxValueakan meluap.
Yaakov Ellis
0

Saya harap membantu Anda.

/// <summary>
/// Get the integer part of any decimal number passed trough a string 
/// </summary>
/// <param name="decimalNumber">String passed</param>
/// <returns>teh integer part , 0 in case of error</returns>
private int GetIntPart(String decimalNumber)
{
    if(!Decimal.TryParse(decimalNumber, NumberStyles.Any , new CultureInfo("en-US"), out decimal dn))
    {
        MessageBox.Show("String " + decimalNumber + " is not in corret format", "GetIntPart", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return default(int);
    } 

    return Convert.ToInt32(Decimal.Truncate(dn));
}
luka
sumber
-2
   Public Function getWholeNumber(number As Decimal) As Integer
    Dim round = Math.Round(number, 0)
    If round > number Then
        Return round - 1
    Else
        Return round
    End If
End Function
Mattheu Norwood
sumber
1
Jawaban yang diterima — diposting lebih dari delapan tahun yang lalu — menjelaskan mengapa jawaban ini salah. Kisarannya decimaljauh lebih besar daripada int. Juga, ini bukan pertanyaan tentang VB.
Joe Farrell
@JoeFarrell - jika Anda merasa jawabannya salah, Anda dapat mempertimbangkan untuk tidak memilihnya selain hanya memberikan komentar. Namun, jangan menandainya (bukan berarti saya mengatakan Anda punya). Ini upaya untuk menjawab pertanyaan itu. Mungkin dalam bahasa yang salah, itu mungkin salah bahkan di VB, tapi ini adalah upaya. Lihat, misalnya, " Ketika sebuah jawaban menjawab pertanyaan yang salah, bukankah itu Jawabannya? ".
Wai Ha Lee