2011-10-14 16 views
19

Tôi đã kiểm tra các tài liệu mà long = int64 đã dao động hơn 900.000.000.000.000tại sao điều này sẽ cho kết quả lâu integer overflow

Đây là mã của tôi:

int r = 99; 
long test1 = r*r*r*r*r; 

khi chạy nó mang lại cho tôi 919.965.907 thay cho đúng 9,509,900,499.

một thử nghiệm

long test2 = 99*99*99*99*99; 

Nó từ chối để biên dịch, nói rằng số nguyên tràn.

Nhưng nếu tôi làm điều này

long test3 = 10100200300; 

này hoạt động tốt.

Trả lời

48

Vấn đề là các chữ "99" đang được coi là một int. Nếu bạn thêm "L", nó sẽ coi nó là một thời gian dài. Để khắc phục vấn đề biên soạn của bạn:

long test2 = 99L * 99L * 99L * 99L * 99L; 

Và để khắc phục các "kết quả không chính xác" do tràn số nguyên:

long r = 99; 
long test1 = r * r * r * r * r; 

Điểm mấu chốt là sự biểu hiện ở bên phải của "=" được đánh giá trước khi gán cho long r được thực hiện.

Có hậu tố đen khác mà bạn có thể quan tâm:

Type Suffix Example 
uint U or u 100U 
long L or l 100L 
ulong UL or ul 100UL 
float F or f 123.45F 
decimal M or m 123.45M 

@ m.edmonson, về câu hỏi của bạn về việc tại sao nó đi ra để 919965907. gì đang xảy ra, đó là giá trị là "gói" xung quanh int.MaxValue. Bạn có thể thấy điều này bằng một chương trình thử nghiệm nhỏ:

int i = 99; // 99 
i *= 99; // 9801 
i *= 99; // 970299 
i *= 99; // 96059601 
i *= 99; // 919965907  should be 9509900499 but comes out to 919965907 
      //      which is (9509900499 % int.MaxValue) 

long k = 9509900499 % int.MaxValue; 

"Gói xung quanh" có nghĩa là gì? Khi bạn vượt quá int.MaxValue bằng 1, giá trị "quay lại" thành int.MinValue.

int j = int.MaxValue; 
j++; 

bool isNowMinValue = (j == int.MinValue); // true, the value has "wrapped around" 

Đây là một chút đơn giản; nếu bạn tìm kiếm "số nguyên tràn", bạn sẽ nhận được một lời giải thích tốt hơn. Đó là giá trị tìm hiểu cách số nguyên (và các loại số khác) được đại diện với 32 bit:

http://en.wikipedia.org/wiki/Signed_number_representations

+0

Câu trả lời hay - bạn có thể giải thích lý do tại sao được một kết quả khác nhau giữa phép nhân dài và số nguyên? –

+0

Bạn có thể làm rõ ý bạn bằng cách gói không? Và những gì thats đã làm với modulus%? –

+0

Tôi tin rằng bạn chỉ cần một '99L', phần còn lại sẽ upcast. –

5

Đó là sử dụng số nguyên nhân:

long r = 99; 
long test1 = r*r*r*r*r; 
3

thử nghiệm thứ hai của bạn không thành công vì mỗi 99 là một số nguyên; thay thế nó bằng phần sau và biên dịch.

long test2 = 99L * 99L * 99L * 99L * 99L; 

Xem chi tiết MSDN Long Documentation để biết chi tiết.

1

Trình biên dịch xem 99 dưới dạng số nguyên, mặc dù kết quả cuối cùng sẽ dài.

Điều này sẽ hiệu quả.

long test2 = 99L*99L*99L*99L*99L; 
4

Khi khác đã nói, nhưng:

long test2 = 99L * 99 * 99 * 99 * 99; 

này sẽ cung cấp cho bạn kết quả chính xác với ít L xung quanh :-)

Điều này xảy ra bởi vì 99L đầu tiên là một long, vì vậy tất cả các phép nhân được thực hiện trong trường "long" và tất cả các số nguyên khác được upcasted thành long trước phép nhân (rõ ràng phép nhân luôn ở giữa 2 số và từ trái sang phải, vì vậy nó giống như (((99L * 99) * 99) * 99) * 99 và mỗi kết quả "một phần" là dài và khiến toán hạng kế tiếp được chuyển đổi thành dài.)

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