Làm cách nào để chuyển đổi một số thập phân thành một số nguyên trong C #?


227

Làm thế nào để tôi chuyển đổi một số thập phân thành một int?


11
Sẽ rất hữu ích khi biết bạn muốn làm tròn đến số int gần nhất hay chỉ thả các số sau số thập phân (nghĩa là: luôn luôn làm tròn xuống)
Dinah

128
Tôi thực sự không nhìn thấy điểm trong việc hạ thấp câu hỏi chính hãng. vâng, câu trả lời có thể được tìm thấy trên google NHƯNG nó sẽ không cải thiện chất lượng của trang web nếu mọi người ngừng đóng mỗi câu hỏi thứ hai? nó không giống như câu hỏi này là thư rác hay bất cứ điều gì và tôi chắc chắn rằng nó sẽ hữu ích cho nhiều người mới đến c #
jay_t55

Câu trả lời:


268

Sử dụng Convert.ToInt32từ mscorlibnhư trong

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

Xem MSDN . Bạn cũng có thể sử dụng Decimal.ToInt32. Một lần nữa, xem MSDN . Cuối cùng, bạn có thể thực hiện một vai trực tiếp như trong

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

trong đó sử dụng toán tử cast rõ ràng. Xem MSDN .


10
Xem ra: Chuyển đổi có một số hành vi đáng ngạc nhiên cho chuyển đổi nhất định ( nullso 0với so với ""). Tôi khuyên bạn không bao giờ nên sử dụng Convert trừ khi bạn thực sự cần sự linh hoạt của nó (tức là trong các tình huống được gõ động)
Eamon Nerbonne

1
-1 vì điều này sẽ không hoạt động đối với các giá trị như binary.MaxValue và binary.MinValue và kết quả là một OverflowException. Tôi tin rằng @Will cung cấp câu trả lời tốt hơn tại đây stackoverflow.com/a/501165/39532
mezoid

8
Hãy cẩn thận, bởi vì Convert.ToInt32Decimal.ToInt32cư xử khác nhau. Từ MSDN: Decimal.ToInt32- Giá trị trả về là phần không thể thiếu của giá trị thập phân; chữ số phân số được cắt ngắn . Convert.ToInt32- Trả về giá trị được làm tròn đến số nguyên có chữ ký 32 bit gần nhất. Nếu giá trị là một nửa giữa hai số nguyên, số chẵn được trả về; nghĩa là, 4,5 được chuyển đổi thành 4 và 5,5 được chuyển đổi thành 6.
vezucci

67

Bạn không thể.

Vâng, tất nhiên bạn có thể , tuy nhiên một int (System.Int32) không đủ lớn để chứa mọi giá trị thập phân có thể.

Điều đó có nghĩa là nếu bạn truyền một số thập phân lớn hơn int.MaxValue, bạn sẽ tràn và nếu số thập phân nhỏ hơn int.MinValue, nó sẽ bị tràn.

Điều gì xảy ra khi bạn dưới / tràn? Một trong hai điều. Nếu bản dựng của bạn không được chọn (nghĩa là CLR không quan tâm nếu bạn làm như vậy), ứng dụng của bạn sẽ tiếp tục sau khi giá trị trên / dưới, nhưng giá trị trong int sẽ không như bạn mong đợi. Điều này có thể dẫn đến các lỗi không liên tục và có thể khó khắc phục. Bạn sẽ kết thúc ứng dụng của mình trong trạng thái không xác định có thể dẫn đến ứng dụng của bạn làm hỏng bất kỳ dữ liệu quan trọng nào mà nó hoạt động. Không tốt.

Nếu hội đồng của bạn được chọn (thuộc tính-> build-> advanced-> kiểm tra tràn / số học hoặc tùy chọn trình biên dịch / kiểm tra), mã của bạn sẽ đưa ra một ngoại lệ khi xảy ra lỗi tràn / tràn. Điều này có lẽ tốt hơn không; tuy nhiên, mặc định cho các hội đồng không phải là để kiểm tra quá / tràn.

Câu hỏi thực sự là "bạn đang cố gắng làm gì?" Không biết yêu cầu của bạn, không ai có thể nói cho bạn biết bạn nên làm gì trong trường hợp này, ngoài điều hiển nhiên: ĐỪNG LÀM NÓ.

Nếu bạn đặc biệt KHÔNG quan tâm, câu trả lời ở đây là hợp lệ. Tuy nhiên, bạn nên truyền đạt sự hiểu biết của mình rằng có thể xảy ra tràn và không thành vấn đề bằng cách gói mã cast của bạn trong một khối không được kiểm tra

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

Bằng cách đó, những người đến sau bạn hiểu rằng bạn không quan tâm và nếu trong tương lai ai đó thay đổi bản dựng của bạn thành / kiểm tra, mã của bạn sẽ không bị hỏng bất ngờ.

Nếu tất cả những gì bạn muốn làm là bỏ phần phân số của số, để lại phần tách rời, bạn có thể sử dụng Math.Truncate.

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

3
Mặc dù tôi nghi ngờ chúng giống nhau ở phần dưới nếu đầu vào là số thập phân, tôi cảm thấy thoải mái hơn khi sử dụng Decimal.Truncate so với Math.Truncate, vì cái sau cũng chấp nhận nhân đôi và do đó có thể hiểu là có thể cắt các số chẵn không phải là cơ sở 10, trái ngược với Decimal.Truncate, đây là một phép cắt thực sự của một số 10 cơ sở.
Brian

7
Bối cảnh không được kiểm tra không áp dụng cho số thập phân; các hoạt động trên số thập phân sẽ ném OverflowExceptions bất kể.
Dave

46
int i = (int)d;

sẽ cung cấp cho bạn số làm tròn xuống.

Nếu bạn muốn làm tròn đến số chẵn gần nhất (nghĩa là> .5 sẽ làm tròn số), bạn có thể sử dụng

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

Nói chung, bạn có thể chuyển giữa tất cả các loại số trong C #. Nếu không có thông tin nào bị mất trong quá trình phân vai, bạn có thể thực hiện nó một cách ngầm định:

int i = 10;
decimal d = i;

mặc dù bạn vẫn có thể làm điều đó một cách rõ ràng nếu bạn muốn:

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

Tuy nhiên, nếu bạn sắp mất thông tin qua các diễn viên, bạn phải làm điều đó một cách rõ ràng (để cho bạn biết rằng bạn có thể đang mất thông tin):

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

Ở đây bạn đang mất ".5". Điều này có thể tốt, nhưng bạn phải rõ ràng về nó và thực hiện một diễn viên rõ ràng để cho bạn biết bạn có thể bị mất thông tin.


1
Bạn thực sự muốn MidpointRounding.AwayFromZero nếu bạn muốn> * .5 luôn tròn lên dựa trên kinh nghiệm của tôi cố gắng ra các mã trên nhìn vào sản lượng mẫu ở đây: msdn.microsoft.com/en-us/library/...
Elijah Lofgren

@ElijahLofgren Điều này phụ thuộc vào: Nếu bạn đang thực hiện thống kê, ToEvennên ngăn chặn sự trôi dạt thống kê. Tuy nhiên, nếu bạn hoạt động với các mặt hàng có tính phí hoặc tiền, AwayFromZerocó vẻ như là lựa chọn đúng đắn.
mbx

22
decimal d = 2;
int i = (int) d;

Điều này sẽ làm việc tốt.


Cẩn thận, với một thông tin chuyển đổi rõ ràng có thể bị mất.
Phaedrus

21
Khi chuyển đổi từ thập phân sang int, thông tin sẽ hầu như luôn bị mất nhưng tôi tin rằng đó là điểm chính.
Dinah


8

System.Decimalthực hiện IConvertablegiao diện, trong đó có một ToInt32()thành viên.

Gọi điện có System.Decimal.ToInt32()làm việc cho bạn không?


2
Từ tài liệu : "API này hỗ trợ cơ sở hạ tầng .NET Framework và không có ý định sử dụng trực tiếp từ mã của bạn". Tại sao không sử dụng Convert.ToInt32?
H.Wolper

7

Một mẹo gọn gàng để làm tròn nhanh là thêm 0,5 trước khi bạn chuyển số thập phân của mình sang số nguyên.

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

Lá vẫn i=10 , nhưng

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

Sẽ làm tròn lên mà i=11.


5
Tại sao phải làm điều này khi có Math.Floor và Math.Cady?
Badaro

Vào thời điểm đó, tôi còn khá mới với C # và vì một số lý do tôi đã không nhận ra các chức năng này tồn tại. Đó thực sự là một mẹo tôi học được từ C / C ++, nơi nó rõ ràng hữu ích hơn.
DeadlyBrad42

1
Nếu giá trị thập phân là -9.3 thì sao?
supercat

6

Tôi thích sử dụng Math.Round , Math.Floor , Math.Cading hoặc Math.Truncate để đặt rõ ràng chế độ làm tròn là phù hợp.

Lưu ý rằng tất cả chúng cũng trả về Decimal - vì Decimal có phạm vi giá trị lớn hơn Int32, do đó bạn sẽ vẫn cần truyền (và kiểm tra mức tràn / tràn).

 checked {
   int i = (int)Math.Floor(d);
 }


6

Làm tròn số thập phân đến số nguyên gần nhất

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

khi nào a = 49.9, sau đób = 50

khi nào a = 49.5, sau đób = 50

khi nào a = 49.4, sau đó b = 49vv


0

Tôi thấy rằng toán tử truyền không hoạt động nếu bạn có một số thập phân được đóng hộp (tức là một giá trị thập phân bên trong một loại đối tượng). Convert.ToInt32 (thập phân là đối tượng) hoạt động tốt trong trường hợp này.

Tình huống này xuất hiện khi truy xuất các giá trị IDENTITY / AUTONUMBER từ cơ sở dữ liệu:

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

Xem 4.3.2 Chuyển đổi bỏ hộp


2
Thêm nhiều hơn vào nó để tham khảo: đó là bởi vì bạn chỉ có thể bỏ hộp đến cùng loại ban đầu. Ở đây SELECT SCOPE_IDENTITY()trả về numeric(38, 0)mà dịch sang decimal.NET. foo.ExecuteScalar()trả về một decimalhộp objectmà không thể được đúc trực tiếp đến một int. (int)(decimal)foo.ExecuteScalar()hoặc Convert.ToInt32(foo.ExecuteScalar())sẽ làm việc.
rageit

0

Không có câu trả lời nào có vẻ như đối phó với OverflowException / UnderflowException xuất phát từ việc cố gắng chuyển đổi một số thập phân nằm ngoài phạm vi của int.

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

Giải pháp này sẽ trả về giá trị int tối đa hoặc tối thiểu có thể nếu giá trị thập phân nằm ngoài phạm vi int. Bạn có thể muốn thêm một số làm tròn với Math.Round, Math.Cading hoặc Math.Floor khi giá trị nằm trong phạm vi int.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.