I was looking over this code to calculate math.sqrt in Java. Why did they use hex values in some of the loops and normal values for variables? What benefits are there to use hex?
Because hex corresponds much more closely to bits that decimal numbers. Each hex digit corresponds to 4 bits (a nibble). So, once you've learned the bitmask associated with each hex digit (0-F), you can do something like "I want a mask for the low order byte":
0xff
or, "I want a mask for the bottom 31 bits":
0x7fffffff
Just for reference:
HEX BIN
0 -> 0000
1 -> 0001
2 -> 0010
3 -> 0011
4 -> 0100
5 -> 0101
6 -> 0110
7 -> 0111
8 -> 1000
9 -> 1001
A -> 1010
B -> 1011
C -> 1100
D -> 1101
E -> 1110
F -> 1111
They probably used hex values because the numbers are easier to remember in hex. For example, 0x7fffffff is the same as 2147483647, but is a lot easier to remember.
Hex is a human readable form of the binary the CPU actually uses. When looking at low level commands it often makes more sense to match the CPU and think in hex,
Related
I was going through a java file and saw this block of code and can't really understand what's happening here. What does the & symbol means here and when I run this, I get the values 2 and 8 respectively.
package com.company;
public class Question_2 {
public static void main(String[] args) {
int mask = 0x000F;
int value = 0x2222;
int f = 90;
int h = 9;
System.out.println(value & mask);
System.out.println(f & h);
}
}
This is The output I get:
2
8
& is a bit wise operation
& is 1 if both bit at the same position is 1 otherwise 0
Also, to perform this operation, your operands will be converted to base 2
90 = 0101 1010 in base 2
09 = 0000 1001 in base 2
_________
0000 1000 which is 8 convert to decimal
000f in hexadecimal = 0000 0000 0000 1111
2222 in hexadecimal = 0010 0010 0010 0010
using & on this is 0000 0000 0000 0010 which is 2 convert to decimal
That is how basic & operator works.
& refers to Bitwise AND operation.
the mask variable used to enable specific bit and disable the others.
in this code,
System.out.println(value & mask);
the mask keeps the first (from right to left) 4 bits and unsets the others, so always the value of the bitwise AND between the mask variable and any value will be less than 15 because 0x000F -> 0000 0000 0000 1111
mathematically: since the mask is 0x000F if the value of & between the mask and any value is zero then the number is dividable by 16 otherwise it's not dividable by 16
& is the bitwise AND operation.
System.out.println(value & mask);
outputs the hex representation of bitwise ANS.
System.out.println(f & h);
outputs the decimal representation of the bitwise AND.
& is smart enough to return the result of the same representation as it's arguments.
& is used as a relational operator to check a conditional statement just like && operator.
but there is a small change in how & takes care of conditional statement. && would first check the first data, if its true then it checks the next one and son on.. but in case of single & character, it just evaluate all conditions even if previous one is a failed one. Thus, any change in the data values due to the conditions will only be reflected in this case.
& can also be used as bitwise operator
println(f & h ) ->
01011010
& 00001001
00001000 -> 8 in decimal
Firstly, apologies if this question ends up being a duplicate.
I am trying to do some stuff with bits in Java. And I have a need to get awkward amounts of bits in a single variable. So I am still using a byte but want to only store like 7 bits or 4 bits.
So lets say I have a byte which is something like '1101 0110' and I want to get the '0110' at the end. I have seen someone do this: (byte)(b & 0x0F) where b is a byte.
So the way I understand what happens here is: b (1101 0110) is ANDed with 0x0F (0000 1111) then turned to int and casted back to byte.
1101 0110 &
0000 1111
---------
0010 0110 -> 0000 0000 0000 0000 0000 0000 0010 0110 -> 0010 0110
In this instance, I did not get the 4 bits, i got the whole byte and not what I started with either. Am I misunderstanding how the bitwise and works?
I am pretty sure that this works somehow, but I am at a loss how.
Could someone explain this please?
I would think that doing the following would yield a more reliable result:
(byte) ((b<<4)>>>4)
This way I can make sure that the first 4 bits are always 0.
Your assumption is incorrect as well as provided example: AND is always reliable. The reason why it's used more often is that it's more flexible. This way you can replace with zeroes not only the highest bits, but any bits you want just supplying the appropriate mask. Also using shift you should pay additional attention to the sign bit which is unnecessary when you use AND.
I was looking into when one would want to/should use the bit shift operators. I understand that we don't need to use them to multiply by two and such, because JIT compilation will take care of that. I came across why do we need to use shift operators in java, and am confused by part of the accepted answer:
For example, say I have two bytes that are the high-order and low-order bytes
of a two-byte (16-bit) unsigned value. Say you need to construct that value.
In Java, that's:
int high = ...;
int low = ...;
int twoByteValue = (high << 8) | low;
You couldn't otherwise do this without a shift operator.
To answer your questions: you use them where you need to use them! and nowhere else.
I know that I'm missing something, because to me it looks like he's just multiplying high by 2^8 and adding it to low (I've never actually seen | used in this context before, but when I plugged in dummy values and ran my code, it looked like it was just adding the two together). What's actually going on here?
EDIT: For reference, I had high = 10 and low = 3.
As an example, lets compose the 16-bit representation of the number 54321: 1101 0100 0011 0001 from its high-order 8 bits and low-order 8 bits.
The high-order 8 bits would be: 1101 0100
The low-order 8 bits would be : 0011 0001
1101 0100 << 8
will produce
1101 0100 0000 0000
We then bitwise OR this (|) against the low order bits
1101 0100 0000 0000
0011 0001
-------------------
1101 0100 0011 0001
We now have the full binary representation on 54321 (assuming I'm using unsigned ints of course)
Edit:
To use your example: high=10 and low=3
high, written out in 8 bits, would be 0000 1010
low, written in the same fashion, would be 0000 0011
If we shift high to the left 8 bits:
0000 1010 0000 0000
If we OR that against low:
0000 1010 0000 0000
0000 0011
-------------------
0000 1010 0000 0011
If we treat this pattern as a decimal integer it would mean 2563
Perhaps the confusing part is that the 10 and 3 independently really hold no meaning at all in this context. It is the composition of the two that has value here.
Perhaps you are reading a file byte by byte but in one part of the file there is a sequence of 16-bit integers. You would have to take every pair of bytes and combine them in exactly this fashion to get the 16-bit integers.
Now imagine if, on a platform where the largest integer possible is 64 bits, you wanted to store an integer that is so large it occupies 128 bits. Well, you could use a trick similar to this one to fudge the math and store that really big integer in two separate values. OK, maybe its more complicated than this example, but hopefully that makes it hit home why we would need bitwise operators like these.
I'm just beginning to learn about file compression and I've run into a bit of a roadblock. I have an application that will encode a string such as "program" as a compressed binary representation "010100111111011000"(note this is still stored as a String).
Encoding
g 111
r 10
a 110
p 010
o 011
m 00
Now I need to write this to the file system using a FileOutputStream, the problem I'm having is, how can I convert the string "010100111111011000" to a byte[]/bytes to be written to the file system with FileOutputStream?
I've never worked with bits/bytes before so I'm kind of at a dead end here.
An introduction to bit-shift operators:
First, we have the left-shift operator, x << n. This will shift all the bits in x left by n bits, filling the new bits with zero:
1111 1111
<< 3: 1111 1000
Next, we have the signed right-shift operator, x >> n. This shifts all the bits in x right by n, copying the sign bit into the new bits:
1111 1111
>> 3: 1111 1111
1000 0000
>> 3: 1111 0000
0111 1111
>> 3: 0000 1111
Finally, we have the zero-fill right-shift operator, x >>> n. This shifts all bits in x right by n bits, filling the new bits with zero:
1111 1111
>>> 3: 0001 1111
You may also find useful the bitwise-or operator, x | y. This compares the bits in each position in x and y, setting the new number's bit on if it was on in either x or y, off otherwise:
1010 0101
| 1010 1010
---------
1010 1111
You should only need the previous operators for the problem at hand, but for the sake of completeness, here are the last two:
The bitwise-and operator, x & y sets the bits in the output to one if and only if the bit is on in both x and y:
1010 0101
& 1010 1010
---------
1010 0000
The bitwise-xor operator, x ^ y sets the output bits to one if the bit is on in one number or the other but not both:
1010 0101
^ 1010 1010
---------
0000 1111
Now, applying these to the situation at hand:
You will need to use the bit-shift operators to add and manipulate bits. Start setting bits at the right side according to their string representations and shift them over. Continue until you hit the end of a byte, and then move to the next byte. Say we want to create a byte representation of "1100 1010":
Our byte Target
--------- --------
0000 0000
1100 1010
0000 0001 ^
1100 1010
0000 0011 ^
1100 1010
0000 0110 ^
1100 1010
0000 1100 ^
1100 1010
0001 1001 ^
1100 1010
0011 0010 ^
1100 1010
0110 0101 ^
1100 1010
1100 1010 ^
I will, of course, leave it to you to apply this to your work.
Chop your String up into lengths of 8 and call Byte#parseByte. If you set the radix to 2, it will parse the String as a binary number.
I guess, you want to write these zeros and ones as binary values in a file. I so, you can iterate the string taking 8 signs everytime (String.substring() or smth) and create bytes with Byte(String) constructor.
It's the easiest solution that comes to my mind for now.
If i'm not right about the problem, tell more about it please.
An integer's max value in Java is 2147483647, since Java integers are signed, right?
0xff000000 has a numeric value of 4278190080.
Yet I see Java code like this:
int ALPHA_MASK = 0xff000000;
Can anyone enlighten me please?
Just an addition to erickson's answer:
As he said, signed integers are stored as two's complements to their respective positive value on most computer architectures.
That is, the whole 2^32 possible values are split up into two sets: one for positive values starting with a 0-bit and one for negative values starting with a 1.
Now, imagine that we're limited to 3-bit numbers. Let's arrange them in a funny way that'll make sense in a second:
000
111 001
110 010
101 011
100
You see that all numbers on the left-hand side start with a 1-bit whereas on the right-hand side they start with a 0. By our earlier decision to declare the former as negative and the latter as positive, we see that 001, 010 and 011 are the only possible positive numbers whereas 111, 110 and 101 are their respective negative counterparts.
Now what do we do with the two numbers that are at the top and the bottom, respectively? 000 should be zero, obviously, and 100 will be the lowest negative number of all which doesn't have a positive counterpart. To summarize:
000 (0)
111 001 (-1 / 1)
110 010 (-2 / 2)
101 011 (-3 / 3)
100 (-4)
You might notice that you can get the bit pattern of -1 (111) by negating 1 (001) and adding 1 (001) to it:
001 (= 1) -> 110 + 001 -> 111 (= -1)
Coming back to your question:
0xff000000 = 1111 1111 0000 0000 0000 0000 0000 0000
We don't have to add further zeros in front of it as we already reached the maximum of 32 bits.
Also, it's obviously a negative number (as it's starting with a 1-bit), so we're now going to calculate its absolute value / positive counterpart:
This means, we'll take the two's complement of
1111 1111 0000 0000 0000 0000 0000 0000
which is
0000 0000 1111 1111 1111 1111 1111 1111
Then we add
0000 0000 0000 0000 0000 0000 0000 0001
and obtain
0000 0001 0000 0000 0000 0000 0000 0000 = 16777216
Therefore, 0xff000000 = -16777216.
The high bit is a sign bit. Setting it denotes a negative number: -16777216.
Java, like most languages, stores signed numbers in 2's complement form. In this case, subtracting 231, or 2147483648 from 0x7F000000, or 2130706432, yields -16777216.
Something probably worth pointing out - this code is not meant to be used as an integer with a numerical value; The purpose is as a bitmask to filter the alpha channel out of a 32 bit color value. This variable really shouldn't even be thought of as a number, just as a binary mask with the high 8 bits turned on.
the extra bit is for the sign
Java ints are twos complement
ints are signed in Java.