2013-03-22 42 views
6

Tôi cố gắng để viết một máy tính bitwise trong java, cái gì mà bạn có thể nhập một biểu thức như ~ 101 và nó sẽ trả lại 10 tuy nhiên khi tôi chạy mã nàyBitwise phủ đưa ra kết quả bất ngờ

import java.util.Scanner; 

public class Test 
{ 
    public static void main(String[] args) 
    { 
     Integer a = Integer.valueOf("101", 2); 
     System.out.println(Integer.toString(~a,2)); 
    } 
} 

nó kết quả đầu ra -110 tại sao?

+6

http: // en.wikipedia.org/wiki/Two's_complement –

+0

Để biết chi tiết, hãy xem: http://stackoverflow.com/q/12337360/44522 – MicSim

Trả lời

8

Bạn giả định rằng 101 dài ba bit. Java không hỗ trợ các hoạt động bit có độ dài thay đổi, nó hoạt động trên toàn bộ các bit int, vì vậy ~ sẽ là not của một bit dài 32 bit "101".

--- Đã chỉnh sửa sau khi được hỏi "Làm cách nào để khắc phục sự cố này?" ---

Đó là câu hỏi thực sự hay, nhưng câu trả lời là sự kết hợp của "bạn không thể" và "bạn có thể đạt được điều tương tự bằng các phương tiện khác nhau".

Bạn không thể sửa chữa toán tử ~, vì nó hoạt động như thế nào. Nó sẽ giống như yêu cầu sửa lỗi + để chỉ thêm địa điểm của 1. Chỉ sẽ không xảy ra.

Bạn có thể đạt được thao tác mong muốn, nhưng bạn cần thêm một chút "công cụ" để làm cho nó hoạt động. Trước tiên, bạn phải có nội dung nào đó (một int khác) chỉ định các bit quan tâm. Điều này thường được gọi là mặt nạ bit bit.

int mask = 0x00000007; // just the last 3 bits. 

int masked_inverse = (~value) & mask; 

Lưu ý rằng những gì chúng tôi đã thực sự đảo ngược 32 bit, sau đó lấy ra 29 số bit đó; bởi vì, chúng được đặt thành 0 trong mặt nạ, có nghĩa là "chúng ta không quan tâm đến chúng". Điều này cũng có thể được tưởng tượng khi tận dụng toán tử & để chúng tôi nói "nếu được đặt và chúng tôi quan tâm đến nó, hãy đặt".

Bây giờ, bạn sẽ vẫn còn có 32 bit, nhưng chỉ có 3 bit thấp hơn sẽ được đảo ngược. Nếu bạn muốn có cấu trúc dữ liệu 3 bit thì đó là một câu chuyện khác. Java (và hầu hết các ngôn ngữ) chỉ không hỗ trợ trực tiếp những thứ đó. Vì vậy, bạn có thể bị cám dỗ để thêm một loại khác loại vào Java để hỗ trợ điều đó. Java thêm các loại thông qua cơ chế lớp, nhưng các loại được cài sẵn không thể thay đổi. Điều này có nghĩa là bạn có thể viết một lớp để biểu diễn cấu trúc dữ liệu 3 bit, nhưng nó sẽ phải xử lý ints nội bộ dưới dạng các trường 32 bit.

May mắn thay cho bạn, ai đó đã thực hiện việc này. Nó là một phần của thư viện Java chuẩn và is called a BitSet.

BitSet threeBits = new BitSet(3); 
threeBits.set(2); // set bit index 2 
threeBits.set(0); // set bit index 0 
threeBits.flip(0,3); 

Tuy nhiên, thao tác chút như có một cảm giác khác nhau cho họ do những hạn chế của hệ thống lớp/đối tượng trong Java, cho phép theo quy định lớp học như chỉ cách thêm các loại mới trong Java.

+0

vì vậy làm cách nào tôi sửa lỗi này –

+0

@JoshSobel Tôi đã cập nhật câu trả lời. Một số câu hỏi thực sự ngắn đòi hỏi giải thích dài, vì họ chỉ đủ may mắn để mở ra cánh cửa của sự hiểu biết mới. Chúc may mắn về nỗ lực của bạn. –

+0

nhưng làm cách nào tôi tự động điều chỉnh mặt nạ sao cho phù hợp với số –

0

Phương thức toString() diễn giải đối số của nó dưới dạng giá trị đã ký.

Để minh họa hoạt động nhị phân, tốt hơn nên sử dụng Integer.toBinaryString(). Nó diễn giải đối số của nó là unsigned, sao cho ~ 101 được xuất dưới dạng 11111111111111111111111111111010.

Nếu bạn muốn ít bit đầu ra hơn, bạn có thể che dấu kết quả bằng &.

0

101 trong số nguyên thực sự được biểu thị là 00000000000000000000000000000101 phủ nhận điều này và bạn nhận được 11111111111111111111111111111010 - đây là -6.

+0

Tôi nghĩ OP tự hỏi tại sao biểu diễn nhị phân của ~ a là '... 111111010', 'toString (~ a, 2)' in '-110'? – Pshemo

1

Nếu a = ...0000101 (bin) = 5 (dec)

~a = ~...0000101(bin) = ...1111010(bin) 

và Java sử dụng "Two's complement" hình thức đại diện cho số tiêu cực như vậy

~a = -6 (dec) 

Bây giờ chênh lệch giữa Integer.toBinaryString(number)Integer.toString(number, 2) cho số âm là

  • toBinaryString trả về Chuỗi ở dạng "Two's complement" nhưng
  • toString(number, 2) tính toán dạng nhị phân như thể số dương và thêm dấu "trừ" nếu đối số là số âm.

Vì vậy toString(number, 2) cho ~a = -6 sẽ

  1. tính toán giá trị nhị phân cho 6 ->0000110,
  2. cắt số không hàng đầu ->110,
  3. add trừ dấu ->-110.
0

Chỉ cần để xây dựng trên câu trả lời Edwin của một chút - nếu bạn đang tìm kiếm để tạo ra một mặt nạ độ dài thay đổi để phát triển các bit quan tâm, bạn có thể muốn có một số chức năng helper:

/** 
* Negate a number, specifying the bits of interest. 
* 
* Negating 52 with an interest of 6 would result in 11 (from 110100 to 001011). 
* Negating 0 with an interest of 32 would result in -1 (equivalent to ~0). 
* 
* @param number the number to negate. 
* @param bitsOfInterest the bits we're interested in limiting ourself to (32 maximum). 
* @return the negated number. 
*/ 
public int negate(int number, int bitsOfInterest) { 
    int negated = ~number; 
    int mask = ~0 >>> (32 - bitsOfInterest); 
    logger.info("Mask for negation is [" + Integer.toBinaryString(mask) + "]"); 
    return negated & mask; 
} 

/** 
* Negate a number, assuming we're interesting in negation of all 31 bits (exluding the sign). 
* 
* Negating 32 in this case would result in ({@link Integer#MAX_VALUE} - 32). 
* 
* @param number the number to negate. 
* @return the negated number. 
*/ 
public int negate(int number) { 
    return negate(number, 31); 
} 
Các vấn đề liên quan