Tôi có thể chuyển đổi dài sang int?


Câu trả lời:


218

Cứ làm đi (int)myLongValue. Nó sẽ làm chính xác những gì bạn muốn (loại bỏ MSB và lấy LSB) trong uncheckedngữ cảnh (là mặc định của trình biên dịch). Nó sẽ ném OverflowExceptionvào checkedngữ cảnh nếu giá trị không phù hợp trong int:

int myIntValue = unchecked((int)myLongValue);

15
Đối với bất kỳ ai khác có cùng câu hỏi tôi đã làm: Lưu ý rằng việc loại bỏ MSB có thể có ảnh hưởng đến dấu hiệu của kết quả. Với cách trên, myIntValuecó thể kết thúc âm khi myLongValuedương ( 4294967294 => -2) và ngược lại ( -4294967296 => 0). Vì vậy, khi thực hiện một CompareTothao tác, chẳng hạn, bạn không thể vui vẻ chuyển kết quả của việc trừ đi cái này sang cái longkhác intvà trả lại cái đó; đối với một số giá trị, so sánh của bạn sẽ mang lại kết quả không chính xác.
TJ Crowder

21
@Chris: new Random()sử dụng Environment.TickCountdưới mui xe; không cần phải gieo hạt bằng tay với đồng hồ tích tắc.
Mehrdad Afshari

@MehrdadAfshari có luôn như vậy không?
Chris Marisic

3
Mặc dù điều này đã xảy ra cách đây nhiều năm, lý do tôi sử dụng nó trong Random mới là vì tôi đã nhận được kết quả chính xác tương tự trong một bài kiểm tra đơn vị và tôi muốn phương sai. Sử dụng số đã cho tôi phương sai.
Chris Marisic

3
Ngữ cảnh mặc định là unchecked, vì vậy trừ khi bạn thay đổi rõ ràng, thì uncheckedtừ khóa (như thể hiện trong câu trả lời này và bình luận của @ ChrisMarisic, v.v.) là không cần thiết, và int myIntValue = (int)myLongValuehoàn toàn tương đương. Tuy nhiên, xin lưu ý rằng bất kể bạn có sử dụng uncheckedtừ khóa hay không, bạn sẽ nhận được hành vi cắt xén thô lỗ phi toán học được mô tả bởi @TJCrowder trong đó dấu hiệu có thể lật trong một số trường hợp tràn. Cách duy nhất để thực sự đảm bảo tính chính xác toán học là sử dụng checked(...)bối cảnh, trong đó những trường hợp đó sẽ đưa ra một ngoại lệ.
Glenn Slayden

35
Convert.ToInt32(myValue);

Mặc dù tôi không biết nó sẽ làm gì khi nó lớn hơn int.MaxValue.


42
"Mặc dù tôi không biết nó sẽ làm gì khi nó lớn hơn int.MaxValue" Nó sẽ ném một thứ OverflowException, đó chính xác là những gì OP không muốn: msdn.microsoft.com/en-us/l Library / d4haekc4.aspx
TJ Crowder

4
Kiểm tra nếu myValue> Integer.Max trước khi chạy convert, nếu bạn cần thực hiện xử lý khác khi myValue> Integer.Max. Convert.ToInt32 (myValue) sẽ tràn (không có ngoại lệ, tôi tin) nếu không. Phương pháp này cũng hoạt động trong VB.NET.
TamusJRoyce

3
Trong khi (int) là hợp lệ, Convert là một câu trả lời tốt hơn. Tốt hơn để có ngoại lệ kỳ lạ hơn dữ liệu kỳ lạ.
Richard ngày

1
@RichardJune Um, không? OP ở đây nói rõ ràng : " Nếu giá trị của long> int.MaxValue, tôi rất vui khi để nó bao quanh. " Tôi có thể thấy tranh luận về tuyên bố của bạn nói chung, nhưng trong trường hợp cụ thể này , không, Convertlà không tốt.
ruffin

if (value > Int32.MaxValue) return Int32.MaxValue; else return Convert.ToInt32( value );
Serge

15

Đôi khi bạn không thực sự quan tâm đến giá trị thực tế, nhưng trong việc sử dụng nó dưới dạng tổng kiểm tra / mã băm . Trong trường hợp này, phương thức tích hợp GetHashCode()là một lựa chọn tốt:

int checkSumAsInt32 = checkSumAsIn64.GetHashCode();

7
Cách đây một thời gian kể từ khi câu trả lời này được đưa ra, mặc dù tôi muốn đề cập rằng việc triển khai mã băm có thể khác nhau giữa các phiên bản .NET. Điều này có thể không thực sự xảy ra, nhưng không có gì đảm bảo rằng giá trị này giống nhau giữa các lần chạy ứng dụng / tên miền khác nhau.
Caramiriel

1
Để thêm vào những gì @Caramiriel đang nói: nếu sử dụng làm mã băm tạm thời , trong phiên ứng dụng hiện tại của bạn, thì đó GetHashCodelà một lựa chọn thích hợp. Nếu bạn theo dõi tổng kiểm tra liên tục - một giá trị sẽ giống nhau khi bạn chạy ứng dụng của mình sau đó, thì đừng sử dụng GetHashCode, vì nó không được đảm bảo là cùng một thuật toán.
ToolmakerSteve

9

Cách an toàn và nhanh nhất là sử dụng Bit Masking trước khi sử dụng ...

int MyInt = (int) ( MyLong & 0xFFFFFFFF )

Giá trị Bit Mask ( 0xFFFFFFFF) sẽ phụ thuộc vào kích thước của Int vì kích thước Int phụ thuộc vào máy.


Cần phải quyết định những gì bạn muốn xảy ra khi kết quả sẽ tràn, hoặc trở thành một số âm. Những gì bạn thể hiện vẫn sẽ tràn, IIRC, bởi vì bạn đang để cho dấu hiệu thông qua. [Như đã đề cập trong một câu trả lời khác, trong uncheckedngữ cảnh bạn sẽ không bị tràn - nhưng bạn không cần che dấu uncheckedđể tránh tràn, do đó, chỉ cần một giải pháp trong checkedngữ cảnh.] Ví dụ cho 16 bit. Ký giữ 16 bit (-32768, 32767). Tạo mặt nạ với 0xFFFF cho phép giá trị lên tới 65535, gây tràn, IIRC. Có thể che dấu để tránh bit dấu, 0x7FFF hoặc 0x7FFFFFFF, nếu chỉ muốn tích cực.
ToolmakerSteve

1

Nó có thể chuyển đổi bằng

Phương thức Convert.ToInt32

Nhưng nó sẽ ném OverflowException nếu giá trị nằm ngoài phạm vi của Kiểu Int32. Một bài kiểm tra cơ bản sẽ cho chúng ta thấy nó hoạt động như thế nào:

long[] numbers = { Int64.MinValue, -1, 0, 121, 340, Int64.MaxValue };
int result;
foreach (long number in numbers)
{
   try {
         result = Convert.ToInt32(number);
        Console.WriteLine("Converted the {0} value {1} to the {2} value {3}.",
                    number.GetType().Name, number,
                    result.GetType().Name, result);
     }
     catch (OverflowException) {
      Console.WriteLine("The {0} value {1} is outside the range of the Int32 type.",
                    number.GetType().Name, number);
     }
}
// The example displays the following output:
//    The Int64 value -9223372036854775808 is outside the range of the Int32 type.
//    Converted the Int64 value -1 to the Int32 value -1.
//    Converted the Int64 value 0 to the Int32 value 0.
//    Converted the Int64 value 121 to the Int32 value 121.
//    Converted the Int64 value 340 to the Int32 value 340.
//    The Int64 value 9223372036854775807 is outside the range of the Int32 type.

Ở đây có một lời giải thích dài hơn.


0

Sẽ không

(int) Math.Min(Int32.MaxValue, longValue)

là cách chính xác, nói một cách toán học?


Điều này sẽ kẹp các longValueđến biểu diễn gần intnếu giá trị ban đầu là rất lớn. Nhưng nó thiếu cách xử lý tương tự đối với các đầu vào quá âm, thay vào đó sẽ mất các bit đáng kể nhất; bạn sẽ cần phải so sánh với Int32.MinValue. Tuy nhiên, áp phích ban đầu dường như không muốn kẹp.
Jeppe Stig Nielsen

IMHO đôi khi tốt hơn để có được ngoại lệ so với giá trị sai, mà Int32.MaxValue sẽ là ...
G. Goncharov

0

Giải pháp sau đây sẽ cắt ngắn thành int.MinValue / int.MaxValue nếu giá trị nằm ngoài giới hạn Integer.

myLong < int.MinValue ? int.MinValue : (myLong > int.MaxValue ? int.MaxValue : (int)myLong)

0

Một cách có thể là sử dụng toán tử modulo để chỉ các giá trị nằm trong phạm vi int32, sau đó chuyển nó thành int.

var intValue= (int)(longValue % Int32.MaxValue);
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.