I'm writing a program with java that uses bitwise operations to: (1) generate and display all power-of-two numbers in the range +128 to -128, and (2) display an arbitray user-input integer. Have to provide two methods- main and display.main method should declare int number = 128, include a while loop that loops while number is >= -128, call the display method which prints the value of its passed-in number parameter, if number is greater than zero, use >>= to right shift if number =0 then use ~ to complement it if number is less than zero <<= left shift, after the while loop ask the user to input any number and call the display method to print that number.display number method receives a number parameter, print numbers value and a tab assign to a local variable named mask the value of 1 shifted left 31 times. this puts a 1 in bit 31 and zeros in all other bits, use a loop to step through all 32 bits, doing the following in each step: use a conditional operator whose condition is (mask & number !=0) to print either a 1 or 0. After every fourt bit print a single space to make output more readable. theres two parts i'm having trouble with, (1) the display number method and (2) the while loop. If i set int number = 128 and perform the while loop to run untill >-128 I would have thought it would run the numbers 128 thru -128 didn't work and I have no idea how to set up the display method that I can call to the loop. I could use some serios help have two days to complete and have been working on it for 3 days and have had no luck at all.
It's one thing asking for help, quite another pasting a homework question in verbatim and expecting the community to do it for you! Don't expect a decent response if you're not even willing to put any effort in.
This is actually a very instructive assignment. I will first provide the code that follows the given instructions almost exactly, and then discuss it part by part.
public class HarveysHomework {
static void display(int number) {
System.out.print(number + "\t");
int mask = 1 << 31;
for (int i = 1; i <= 32; i++) {
System.out.print((mask & number) != 0 ? 1 : 0);
mask >>>= 1;
if (i % 4 == 0) {
System.out.print(" ");
}
}
System.out.println();
}
public static void main(String[] args) {
int number = 128;
while (number >= -128) {
display(number);
if (number > 0) {
number >>= 1;
} else if (number == 0) {
number = ~number;
} else {
number <<= 1;
}
}
System.out.print("Input any number: ");
number = new java.util.Scanner(System.in).nextInt();
display(number);
}
}
Here's where the code differs from the specification:
- the implied third
if
in thewhile
from the specification is omitted since it's not necessary - usage of
java.util.Scanner
is not explicitly in the specification - the condition for the ternary operator is re-parenthesized to follow precedence rules
- right shifting of
mask
was missing from the specification - the use of
%
is not from the specification
It's important to learn the process from doing this assignment. First and foremost, get Eclipse; it makes your life so much easier (many homework questions on stackoverflow could've been avoided if students would just use an IDE).
Then here's what I did:
- stub class with empty
display
andmain
- stub
display
to onlyprintln(number);
- write the
while
inmain
as specified- RUN IT NOW make sure it's correct
- write the last 3 lines of
main
- RUN IT NOW make sure it's correct
- now finish up
display
- write everything but the
for
loop body - now finish up the loop body
- ignore the space issue for now, just write out the rest
- RUN IT NOW make sure it's correct
- OOOPS! I used arithmetic right shift on
mask
! Fix it to use logical right shift!- RUN IT NOW make sure it's correct
- now add the spacing code
- RUN IT NOW make sure it's correct
- ignore the space issue for now, just write out the rest
- write everything but the
- DONE!!!
It should be noted that what I did chronologically mimics the progression of details laid out in the specification.
Now let's talk about some bits not mentioned in the specification:
mask >>>= 1;
This is missing from the specification, but if you understood the assignment, you'd have figured it out for yourself. The idea is that mask
is being used to test if each bit of number
is 0
or 1
, going from bit 31 to bit 0. An easy way to do this is to initialize mask = 1 << 31;
as specified, then right shift it one at a time.
Logical right shift is necessary here because you do not want any sign extensions (note that bit 31 in a Java int
is the sign bit). You want mask
to have only one bit set, at the position you're testing for. This is why the logical right shift is used.
This bit of code is also not explicitly from the specification:
if (i % 4 == 0) //...
This is a standard trick for these scenarios. In the for
loop, i
goes from 1
to 32
, and (i % 4 == 0)
precisely when i == 4, 8, 16, 32
. Not coincidentally, that's precisely when you want to insert the single spaces.
You could, in the spirit of the assignment, use bit masking operation instead:
if ((i & 3) == 0) //...
Here, we check the lowest 2 bits of i
to see if they're both zeroes. This is a sufficient and necessary condition for a number to be divisible by 4.
Now let's address some of your remarks:
If I set
int number = 128
and perform thewhile
loop to run until>-128
I would have thought it would run the numbers128
thru-128
There are some crucial mistakes in your statements. The problem statement asks that your program loop "while number is >= -128
". This is not the same as performing the loop "until (the number is) >-128
". It would've been correct had you said it performs the loop "until (the number is)
<-128", but regardless, this is evidence why it's best not to think in
until` logic in the first place.
Some programming languages have an until
construct; Java only has while
and for
. while and
forare similar in that they loop as long as the condition is
true. An
untilis the exact opposite: it loops as long as the condition is
false` instead.
until
can be seen as a syntactic sugar for while
with the terminating condition negated. That is, had Java had until
, the following two loops would've been equivalent:
do {
// something
} until (timeToStop);
do {
// something
} while (!timeToStop);
Perhaps it was decided that until
is therefore unnecessary, and is likely to cause confusion instead for being the odd one out.
Your second crucial mistake is thinking that the loop would "run the numbers 128
thru -128
" because of the way it's set up. Keep in mind that the while
loop at its core doesn't have a concept of having to go through a whole range of numbers, or repeating something some N
number of times; it just does what it's asked to do while something is true
! IT'S YOUR JOB to craft the loop so that it does what you want the number of times that you want, and that it terminates when it does.
Look at this simple example:
int number = 128;
while (number >= -128) {
display(number);
number = -1000;
}
Here just like you said, we initialize number = 128
and we loop while (number >= -128)
, but it doesn't run through all numbers from 128
to -128
. It just displays one number, 128
.
You can't analyze a loop just from its bits and pieces. You have to analyze it as a whole (and yes, sometimes this can be a very difficult task).
In this case, number
actually takes these successive values:
128, 64, 32, 16, 8, 4, 2, 1, 0, -1, -2, -4, -8, -16, -32, -64, -128, -256
|_________________________| | |__________________________________| |
number >>= 1 | number <<= 1 |
| exit
number = ~number
(see reference)
References:
Java Language Specification
- JLS 15.19 Shift Operators
- "The value of
n>>s
isn
right-shifteds
bit positions with sign-extension" - "The value of
n>>>s
isn
right-shifteds
bit positions with zero-extension"
- "The value of
- JLS 15.17.3 Remainder Operator %
- "The binary
%
operator is said to yield the remainder of its operands from an implied division; the left-hand operand is the dividend and the right-hand operand is the divisor"
- "The binary
- JLS 15.15.5 Bitwise Complement Operator
- "note that, in all cases,
~x
equals(-x)-1
"
- "note that, in all cases,
On bit manipulations
- "Why ~0 == -1 ?" (on stackoverflow)
- Bit manipulation (on wikipedia)
- Bit twiddling hacks (the one and only!)