2012-06-29 21 views
13
 string[] strArray = new string[10] { "21.65", "30.90", "20.42", "10.00", "14.87", "72.19", "36.00", "45.11", "18.66", "22.22" }; 
     float temp = 0.0f; 
     Int32 resConvert = 0; 
     Int32 resCast = 0; 
     for (int i = 0; i < strArray.Length; i++) 
     { 
      float.TryParse(strArray[i], out temp); 
      resConvert = Convert.ToInt32(temp * 100); 
      resCast = (Int32)(temp * 100); 
      Console.WriteLine("Convert: " + resConvert + " ExplCast: " + resCast); 
     } 

Ans:Integer chuyển đổi trong C#

Convert: 2165 ExplCast: 2164 // ?? 
    Convert: 3090 ExplCast: 3089 // ?? 
    Convert: 2042 ExplCast: 2042 
    Convert: 1000 ExplCast: 1000 
    Convert: 1487 ExplCast: 1486 //?? 
    Convert: 7219 ExplCast: 7219 
    Convert: 3600 ExplCast: 3600 
    Convert: 4511 ExplCast: 4511 
    Convert: 1866 ExplCast: 1865 //?? 
    Convert: 2222 ExplCast: 2221 //?? 

Tại sao giá trị khác đôi khi trong khi làm Cast Explicit, nhưng không phải lúc nào. Bất kỳ lý do gì?

+0

thử Int64 tại vị trí Int32 –

+0

@Rana: Sự cố với Int32 là gì? Bất kỳ lý do cụ thể? –

+1

R.S. Rana: Điều đó vô lý đối với những giá trị nhỏ bé. – Joey

Trả lời

9

Để lấy một ví dụ, định dạng 21.65 ở định dạng float được biểu thị bằng số như 21.6499999. Các Convert.ToInt32 làm tròn số đến số nguyên gần nhất, năng suất 21,65, trong khi các diễn viên rõ ràng (Int32) chỉ cắt ngắn (làm tròn về phía không), vì vậy bạn nhận được 21,64.

Nếu bạn muốn các số dấu phẩy động được thể hiện trong máy tính giống như cách chúng được in ra, hãy sử dụng decimal thay vì float hoặc double.

+0

Cảm ơn bạn đã trả lời Gabe. Nhưng tại sao nó không phải là trong tất cả các kịch bản. Ví dụ: Chuyển đổi: 4511 ExplCast: 4511 // OK Chuyển đổi: 2222 ExplCast: 2221 // ?? –

+1

22.22 không thể được mã hóa chính xác dưới dạng số dấu phẩy động. Khi bạn nhân với 100, bạn kết thúc bằng một giá trị giống như 2221.999999 – spender

+0

Làm tròn từng bước là hành vi '.Round' mặc định trong .NET phải không? Xem http://stackoverflow.com/questions/311696/why-does-net-use-bankers-rounding-as-default –

4

Convert.ToInt32rounds to the nearest integer, dàn diễn viên trực tiếp chỉ cắt ngắn số. Vì vậy, nếu bạn, do thiếu điểm bất động, có giá trị là 2165.99999whatever thay vì 2165.0, dàn diễn viên trực tiếp cắt tất cả sau dấu phẩy động, trong khi Convert.ToInt32 làm tròn số nguyên gần nhất.

Ví dụ:
22.22f * 100.0f kết quả bằng một cái gì đó như 2221.99993133544921875.
Vì vậy, Convert.ToInt32 sẽ làm tròn nó lên với giá trị mong đợi 2222, trong khi diễn viên sẽ cắt ngắn nó thành 2221.

45.11f * 100.0f về kết quả Mặt khác trong khoảng 4511.00006103515625,
Convert.ToInt32 vòng xuống, mà kết quả trong 4511, kết quả tương tự như khi đúc trực tiếp.

+0

Cảm ơn bạn, không biết rằng – Kane

1

Tôi nghĩ bạn sẽ thấy vấn đề là do sự thiếu chính xác với độ chính xác của dấu chấm động, cụ thể là sử dụng float. Bạn sẽ thấy vấn đề biến mất khi sử dụng decimal. Có một câu trả lời thực sự tốt về sự khác biệt giữa số thập phân và số double (và dấu phẩy) tại đây: decimal vs double! - Which one should I use and when?

+0

Xin chào một lần nữa @Kane. Điều này là gây hiểu lầm. Hãy thử điều này: (int) ((1m/3m) * 300m) (gợi ý, nó không phải là 100). Số thập phân có thể phù hợp hơn đối với một số loại số, nhị phân nổi cho người khác, nhưng cả hai đều dễ bị loại vấn đề này. (nhưng trong trường hợp chuỗi thập phân được phân tích cú pháp, số thập phân thực sự sẽ là đúng cách để đi) – spender

2

Tiếp theo từ câu trả lời Botz3000, phần có liên quan từ MSDN:

Convert.ToInt32 Method (Single)

Return Loại giá trị: giá trị System.Int32, làm tròn tới 32-bit số nguyên ký kết. Nếu giá trị nằm giữa hai số nguyên, thì số chẵn sẽ được trả lại; có nghĩa là, 4.5 được chuyển đến 4, và 5,5 được chuyển đổi sang 6.

Explicit Numeric Conversions Table

• Khi bạn chuyển đổi từ một giá trị gấp đôi hoặc phao đến một loại không thể thiếu, giá trị được làm tròn về 0 đến giá trị tích phân gần nhất.Nếu giá trị tích phân kết quả nằm ngoài phạm vi giá trị đích , kết quả phụ thuộc vào ngữ cảnh kiểm tra tràn. Trong một ngữ cảnh được kiểm tra , một Luồng thừa được ném ra, trong khi trong ngữ cảnh không được chọn, kết quả là giá trị không xác định của loại đích.

1

Calling Convert.ToInt32 cũng giống như cách gọi:

(int) Math.Round(floatValue, 0);

Direct Đúc cũng giống như gọi Tầng

(int) Math.Floor(float);

luôn mang đến cho bạn một giá trị nhỏ hơn hoặc bằng giá trị bạn cung cấp trong đối số. Biểu diễn điểm nổi không "chính xác". Vì vậy, 21,65 có thể được đại diện là 21.649999 hoặc tương tự vì không có đủ độ chính xác.

Vì vậy: 21,65 * 100 = 2164,9999 Sàn giá trị này sẽ cho bạn một số nguyên đó là nhỏ hơn hoặc bằng 2164,9 ... ví dụ: 2164

Làm tròn 2164,99 mặt khác sẽ cung cấp cho bạn: 2165

Bạn có thể nhìn thấy hiệu quả ở đây:

Console.WriteLine(Math.Round(21.65f*100)); //2165 
Console.WriteLine(Math.Floor(21.65f*100)); //2164 

Sử dụng đôi thay vì phao của (chính xác hơn, nhưng vẫn không vô hạn):

012.
Console.WriteLine(Math.Round(21.65d*100)); //2165 
Console.WriteLine(Math.Floor(21.65d*100)); //2165 
+0

Cảm ơn bạn đã trả lời. Nhưng tại sao nó không phải là trong tất cả các trường hợp –

+0

Ah, đó là vì cách các số dấu chấm động được lưu trữ trong bộ nhớ. Một số số có thể được biểu diễn chính xác, một số số không thể.Tải chi tiết đẫm máu ở đây: http://en.wikipedia.org/wiki/Single_precision – Grynn

+1

Hãy thử trang này: http://www.binaryconvert.com/result_float.html?decimal=050049046054053 Biểu diễn tốt nhất là 21.65 = 2.16499996185302734375E1 Các đại diện tốt nhất của 20,42 = 2,042E3 (tốt đẹp và chính xác!) – Grynn

Các vấn đề liên quan