2012-02-22 24 views
18

System.out.println(Integer.MAX_VALUE + 1 == Integer.MIN_VALUE);tại sao Integer.MAX_VALUE + 1 == Integer.MIN_VALUE?

là đúng.

Tôi hiểu rằng số nguyên trong Java là 32 bit và không thể vượt quá 2^31-1, nhưng tôi không thể hiểu tại sao thêm 1 vào MAX_VALUE kết quả trong MIN_VALUE và không phải trong một số loại ngoại lệ. Không đề cập đến một cái gì đó như chuyển đổi trong suốt sang một loại lớn hơn, giống như Ruby.

Hành vi này có được chỉ định ở đâu đó không? Tôi có thể dựa vào nó?

+0

nhiều câu trả lời hay tại đây ngay bây giờ, tuy nhiên, giờ đây tôi rất tò mò về lý do bạn hỏi "Tôi có thể dựa vào nó không?" - tại sao bạn muốn dựa vào nó? – Brian

+0

nó có thể là một câu hỏi khác, --- Tôi đang tìm một số 'iterator' sẽ lặp lại một mảng bắt đầu từ phần tử N, sau đó sau khi đến phần tử cuối bắt đầu lặp từ phần tử 0 đến phần tử N-1 --- và số nguyên này hành vi có thể hữu ích cho điều đó ... nhưng tôi đã kết thúc chỉ với hai vòng lặp khác nhau –

+3

Để tham khảo, nếu bạn muốn nhận ngoại lệ, một số thư viện cung cấp các phương thức: [Guava] (http: //docs.guava-libraries. googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html#checkedAdd(int,%20int)) [Apache] (http://commons.apache.org/math/api- 2.2/org/apache/commons/math/util/MathUtils.html # addAndCheck (int,% 20int)) –

Trả lời

27

Vì số nguyên tràn. Khi nó tràn, giá trị tiếp theo là Integer.MIN_VALUE. Relevant JLS

Nếu số nguyên bổ sung tràn, thì kết quả là các bit bậc thấp của tổng toán học như được trình bày ở một số định dạng bổ sung đủ lớn hai. Nếu tràn xảy ra, thì dấu của kết quả không giống như dấu của tổng toán học của hai giá trị toán hạng.

4

Lý do tương tự tại sao ngày thay đổi khi bạn vượt qua dòng ngày quốc tế: có sự gián đoạn tại đó. Nó được xây dựng vào bản chất của bổ sung nhị phân.

8

Bạn phải hiểu làm thế nào các giá trị số nguyên được biểu diễn dưới dạng nhị phân, và cách thức hoạt động Ngoài nhị phân. Java sử dụng một biểu diễn được gọi là bổ sung của hai, trong đó bit đầu tiên của số đại diện cho dấu của nó. Bất cứ khi nào bạn thêm 1 vào số nguyên Java lớn nhất, có dấu bit là 0, thì ký hiệu bit của nó trở thành 1 và số sẽ trở thành số âm.

liên kết này giải thích với các chi tiết: http://www.cs.grinnell.edu/~rebelsky/Espresso/Readings/binary.html#integers-in-java

-

Java Language Specification đối xử với hành vi này ở đây: http://docs.oracle.com/javase/specs/jls/se6/html/expressions.html#15.18.2

Nếu một sự bổ sung số nguyên tràn, sau đó kết quả là thấp các bit theo thứ tự của tổng toán học như được biểu diễn trong một số định dạng bổ sung hai của đủ lớn. Nếu tràn xảy ra, thì dấu của kết quả không giống như dấu của tổng toán học của hai giá trị toán hạng.

Điều đó có nghĩa là bạn có thể dựa vào hành vi này.

3

Khi bạn thêm 3 (ở dạng nhị phân 11) đến 1 (trong hệ nhị phân 1), bạn phải thay đổi để 0 (ở dạng nhị phân 0) tất cả các nhị phân 1 bắt đầu từ bên phải, cho đến khi bạn nhận được 0, mà bạn nên thay đổi để 1 . Integer.MAX_VALUE có tất cả các địa điểm được điền đầy đủ với 1 do đó chỉ còn lại 0 s.

21

Việc lưu trữ số nguyên được tràn và that is not indicated in any way, as stated in JSL 3rd Ed.:

Các nhà khai thác nguyên built-in không chỉ tràn hoặc tràn dưới bất kỳ cách nào.Toán tử số nguyên có thể ném một NullPointerException nếu chuyển đổi unboxing (§5.1.8) của tham chiếu null là bắt buộc. Ngoài ra, các nhà khai thác số nguyên duy nhất có thể ném một ngoại lệ (§11) là các nhà điều hành số nguyên chia /(§15.17.2) và các nhà điều hành số nguyên còn lại %(§15.17.3), mà ném một ArithmeticException nếu toán hạng bên phải là zero, và thặng dư và sụt lần khai thác ++ (§15.15.1, §15.15.2) và -- (§15.14.3, §15.14.2), có thể ném OutOfMemoryError nếu chuyển đổi quyền anh là (§5.1.7) và không có đủ bộ nhớ để thực hiện chuyển đổi.

Ví dụ trong một lưu trữ 4-bit:

MAX_INT: 0111 (7) 
MIN_INT: 1000 (-8) 

MAX_INT + 1:

0111+ 
0001 
---- 
1000 
4

Đây là một vấn đề nổi tiếng liên quan đến thực tế là số nguyên được biểu diễn dưới dạng two's complement xuống lớp nhị phân. Khi bạn thêm 1 vào giá trị lớn nhất của số bổ sung của hai bạn sẽ nhận được giá trị nhỏ nhất. Thành thật mà nói, tất cả các số nguyên hoạt động theo cách này trước khi java tồn tại, và thay đổi hành vi này đối với ngôn ngữ Java sẽ làm tăng thêm chi phí cho toán số nguyên và các lập trình viên bối rối đến từ các ngôn ngữ khác.

3

Trên hầu hết các bộ xử lý, hướng dẫn số học không có chế độ lỗi khi tràn. Họ đặt cờ phải được kiểm tra. Đó là một hướng dẫn bổ sung nên có lẽ chậm hơn. Để việc triển khai ngôn ngữ càng nhanh càng tốt, các ngôn ngữ thường được chỉ định để bỏ qua lỗi và tiếp tục. Đối với Java, hành vi được xác định trong JLS. Đối với C, ngôn ngữ không chỉ rõ hành vi, nhưng các bộ vi xử lý hiện đại sẽ hoạt động như Java.

Tôi tin rằng có các đề xuất cho các thư viện Java SE 8 (vụng về) để ném tràn, cũng như các hoạt động chưa ký. Một hành vi, tôi tin rằng phổ biến trong thế giới DSP, là kẹp các giá trị ở mức tối đa, vì vậy Integer.MAX_VALUE + 1 == Integer.MAX_VALUE [không phải Java].

Tôi chắc chắn rằng các ngôn ngữ trong tương lai sẽ sử dụng ints chính xác tùy ý, nhưng không phải trong một thời gian. Yêu cầu thiết kế trình biên dịch tốn kém hơn để chạy nhanh.