I have the following loop:
for (byte i = 0 ; i < 128; i++) {
System.out.println(i + 1 + " " + name);
}
When I execute my programm it prints all numbers from -128 to 127 in an infinite loop. Why does this happen?
byte is a 1-byte type so can vary between -128...127, so condition i < 128 is always true. When you add 1 to 127 it overflows and becomes -128 and so on in a (infinite) loop...
After 127, when it increments, it will become -128, so your condition won't match .
byte: The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive). The byte data type can be useful for saving memory in large arrays, where the memory savings actually matters. They can also be used in place of int where their limits help to clarify your code; the fact that a variable's range is limited can serve as a form of documentation.
It will work like this:
0, 1, 2, ..., 126, 127, -128, -127, ...
as 8 bits can represent a signed number up to 127.
See here for the primitive data types.
Picture says more than words
Because bytes are signed in Java so they will always be less than 128.
Why Java chose signed bytes is a mystery from the depths of time. I've never been able to understand why they corrupted a perfectly good unsigned data type :-)
Try this instead:
for (byte i = 0 ; i >= 0; ++i ) {
or, better yet:
for (int i = 0 ; i < 128; ++i ) {
because when i == 127 and and you executes i++ it overflows to -128.
The type byte has a range of -128..127. So i is always less than 128.
Alright, so the reason behind this has been answered already, but in case you were interested in some background:
A bit is the smallest unit of storage which the computer can recognize (n.b. not the smallest number). A bit is either a 0 or a 1.
A byte is an 8 bit data type, meaning it is composed of 8 bit strings such as 10101010 or 0001110. Using simple combinatorics, we know that there are 2^8 = 256 possible combinations of bytes.
If we wanted to only represent positive numbers, we could do a straight conversion from base 2 to base 10. The way that works is, for a bit string b7b6b5b4b3b2b1b0 the number in decimal is dec = sum from n=0 to 7 of (bn * 2^n).
By only representing positive numbers ( an unsigned byte) we can represent 256 possible numbers in the range 0 to 255 inclusive.
The problem comes in when we want to represent signed data. A naive approach (n.b. this is for background, not the way java does it) is to take the left most bit and make it the sign bit where 1 is negative and 0 is positive. So for example 00010110 would be 21 and 10010110 would be -21.
There are two major problems with such a system. The first is that 00000000 is 0 and 10000000 is -0, but as everyone knows, there is no -0 that is somehow different from 0, but such a system allows for the number and 0 ≠ -0. The second problem is that, due to representing two zeroes, the system only allows for representing numbers from -127 to 127, a range of only 254 (2 less than before).
A much better system (and the one which most systems use) is called Two's Compliment. In Two's Compliment, the positive numbers are represented with their normal bit string where the leftmost bit is 0. Negative numbers are represented with the left most bit as a 1 and then calculating the two's compliment for that number (from whence the system gets its name)
Although mathematically it is a slightly more complex process, because we are dealing with the number 2 there are some short cuts. Essentially, you can take the positive version and (from right to left) take all zeroes until you hit a 1. Copy those zeroes and one, then take the NOT of the rest of the bits. So for example, to get -21, positive 21 is 00010110 we take the 10 and not the rest to get 11101010, the two's compliment representation of -21.
Two's Compliment is a much more difficult system to grasp, but it avoids the previously stated problems, and for an n-bit number can represent all digits from -2^(n-1) to 2^(n-1)-1 which for our byte means -128 to 127 (hence the problem in this question)
A couple of notes:
- This is for integer representation only. Real number representation is another system entirely (if there is a request for it, I'm sure we could make a number representation CW post)
- Wikipedia has a couple more number representation systems if you're interested.
Best is if you do
for (byte i = 0 ; i < Byte.MAX_VALUE; i++ ) {
System.out.println( i + 1 + " " + name );
}
this should work
for (byte i = 0 ; i<128; ++i ) {
if(i==-128)
break;
System.out.println( i + 1 + " " + "name" );
}
Related
I am working on a file reader and came into a problem when trying to read a short. In short (punintended), java is converting a two bytes I'm using to make the short into an int to do bitwise operations and is converting it in a way to keep the same value. I need to convert the byte into an int in a way that would preserve its value so the bits stayed the same.
example of what's happening:
byte number = -1; //-1
int otherNumber = 1;
number | otherNumber; // -1
example of what I want:
byte number = -1; //-1
int otherNumber = 1;
number | otherNumber; // 129
This can be done pretty easily with some bit magic.
I'm sure you're aware that a short is 16 bits (2 bytes) and an int is 32 bits (4 bytes). So, between an integer and a short, there is a two-byte difference. Now, for positive numbers, copying the value of a short to an int is effectively copying the binary data, however, as you've pointed out, this is not the case for negative numbers.
Now let's look at how negative numbers are represented in binary. It's a bit confusing, so I'll try to keep it simple. Modern systems use what's called the two's compliment to store negative numbers. Basically all this means is that the very first bit in the set of bytes representing the number determines whether or not it's negative. For mathematical purposes, the rest of the bits are also inverted and offset 1 bit to the right (since you can't have negative 0). For example, 2 as a short would be represented as 0000 0000 0000 0010, while -2 would be represented as 1111 1111 1111 1110. Now, since the bytes are inverted in a negative number, this means that -2 in int form is the same but with 2 more bytes (16 bits) at the beginning that are all set to 1.
So, in order to combat this, all we need to do is change the extra 1s to 0s. This can be done by simply using the bitwise and operator. This operator goes through each bit and checks if the bits at each position in each operand are a 1 or a 0. If they're both 1, the bit is flipped to a 0. If not, nothing happens.
Now, with this knowledge, all we need to do is create another integer where the first two bytes are all 1. This is fairly simple to do using hexidecimal literals. Since they are an integer by default, we simply need to use this to get four bytes of 1s. With a single byte, if you were to set every bit to 1, the max value you can get is 255. 255 in hex is 0xFF, so 2 bytes would be 0xFFFF. Pretty simple, now you just need to apply it.
Here is an example that does exactly that:
short a = -2;
int b = a & 0xFFFF;
You could also use Short.toUnsignedInt(), but where's the fun in that? 😉
In java, short has range of -128 to 127. Why is it not -127 to 127 ? Considering one bit is used for storing the sign of the number, the negative limit should have been -127 which is sum of 2^6+2^5+2^4+2^3+2^2+2^1+2^0 ? What am I missing in my calculations ?
I will assume you meant byte rather than short, as short has a range of -32768 to 32767.
You appear to be under the impression that, for integer types (including short), a negative number is represented with a signed bit and the rest of the number as normal. So -1 would be represented as 1000.0001 (dot added for readability). This, however, is incorrect.
In reality, -1 is represented as 1111.1111, and 1000.0000 is actually -128 (and not -0, which doesn't exist for this type). This is to keep the arithmetic consistent across all values.
You are using 8-Bits to store that in the memory of the computer. This would simply 0 to 255. Considering that you also want negative numbers, you must change the way of looking on these numbers.
Let's say that we take the 8th bit as an indicator for negativity. The negative number would be the negation of the positive number. This would let us display numbers from -127 to 127, but there would be two ways to display the 0: 1111 1111 and 0000 0000. This is called One's Complement.
Because engineers wanted to use all the available space, the came up with a new idea. To convert a position number in to a negative ( * - 1) they decided to fully negate the number and increment it by one. This would give them the possibility of using the whole 256 range. That's the Two's Complement. There are 128 negative numbers + 1 Zero + 127 positive numbers, which makes 256 numbers.
Your calculations are wrong. Total possibilities are 2^8 and that is equal to 256. From -128 to 127 because we count 0 as one of those numbers. 128+128 = 256. But 256 + '0' = 257. So it has to be from -128 to 127.
In java when I say Integer i = Math.abs(Integer.MIN_VALUE). I get the same value as the answer,which means i contains Integer.MIN_VALUE.
I have verified the same in C++ as well.
Why this behavior?
Read this in Effective Java by Joshua Bloch.
I found the answer for this question and here is the explanation:
Computers work with binary arithmentic, the logic of Math.abs in java or the absolute function in any language is like below:
if(num >= 0)
return num;
else
return (2's complement of the num);
Note : How to find 2's complement
For a given number, we find it's 1's complement first and then add 1 to it. For e.g.
Consider our number to be 10101
1's complement= 01010
2's complement= 01011 (added 1 to the 1`s complement)
Now, for the sake of making it easy and clear, let us say that our Integer(signed) size is 3 bit, then here is the possible list of numbers which can be produced using the four bits:
000 --> 0 (0)
001 --> 1 (1)
010 --> 2 (2)
011 --> 3 (3)
100 --> 4 (-4)
101 --> 5 (-3)
110 --> 6 (-2)
111 --> 7 (-1)
Now that this is signed, it means half of the numbers are negative and the other half are positive(The negative numbers are the ones with the first bit 1). Let us start from 000 and try to find its negative number, it would be the two's complement of 000.
2's complement of `000` = 1 + `111` = `000`
2's complement of `001` = 1 + `110` = `111`
2's complement of `010` = 1 + `101` = `110`
2's complement of `011` = 1 + `100` = `101`
2's complement of `100` = 1 + `011` = `100`
2's complement of `101` = 1 + `010` = `011`
2's complement of `110` = 1 + `001` = `010`
2's complement of `111` = 1 + `000` = `001`
From the above demonstration, we find that 2's complement of 111(-1) is 001(1), similarly 2's complement of 110(-2) is 010(2), 2's complement of 101(-3) is 011(3) and 2's complement of 100(-4) is 100(-4) and as we can see that -4 is the smallest negative number possible using 3 bits.
This is the reason why absolute of Integer.MIN_VALUE is Integer.MIN_VALUE.
There is an inherent asymmetry that is the root cause of this effect. The number of 32-bit bit patterns is even. One of those patterns is used for zero. That leaves an odd number of non-zero values. The number of positive values and the number of negative values cannot be equal because their sum is odd.
In the 2's complement representation used for Java integers, the number of negative numbers is one greater than the number of positive numbers. Each negative number other than Integer.MIN_VALUE corresponds to a positive number that is both its negation and its absolute value. Integer.MIN_VALUE is left over, with no corresponding positive int. Math.abs and negation map it to itself.
Why this behavior?
It is a mathematical consequence of the choice of representation used in all modern computers.
Here's an informal proof of why it has to be that way.
A signed binary number representation with N bits has 2N possible values; i.e. a set integers with an even number of elements.
Remove zero from the set. The set is now has an odd number of elements.
Now remove all pairs of numbers of the form {n, -n}. Each time we remove a pair of numbers, the set still contains an odd number of elements.
We are now left with a set that contains an odd number of integers for which n is in the set, but -n is not in the set. Since the set size is odd, it cannot be empty; i.e. there is at least one number with this property.
In the representations specified by Java (and indeed used all other practical languages), integer types have 2N-1 negative values and 2N-1 - 1 values greater than zero. The value that has the strange property is MIN_VALUE. This representation is called two's complement.
Strictly speaking, an integer representation doesn't have to have this anomaly:
It is possible to have two zeros (-0 and +0); e.g. signed magnitude or one's complement representations. (This invalidates step 2 of the proof: there are now 2 zeros to remove.)
It is possible to exclude -2N-1; i.e. make it an illegal value. (This invalidates step 1 of the proof: the initial set now has an odd number of values.)
It is possible to specify integer arithmetic so that (for example) negating MIN_VALUE raises an exception. For instance Math.abs(Integer.MIN_VALUE) would throw an exception.
However, all of these things have significant performance implications, especially since modern computer hardware only supports twos-complement arithmetic natively. They also have issues in relation to writing reliable integer codes ...
Math.abs(int) docs says If the argument is negative, the negation of the argument is returned. JLS 15.15.4. Unary Minus Operator says For all integer values x, -x equals (~x)+1.
-Integer.MIN_VALUE = ~Integer.MIN_VALUE + 1 = ~0x80000000 + 1 = 0x7FFFFFFF + 1 = 0x80000000 = Integer.MIN_VALUE
You might expect that absolute value of Integer.MIN_VALUE would be Integer.MAX_VALUE + 1, but this value is out of primitive int size. And Integer.MAX_VALUE + 1 is Integer.MIN_VALUE again. That's all.
This is because of the way two's-complement number systems work. Integer.MIN_VALUE corresponds to 0x80000000. The standard way to negate it is to take its ones' complement (0x7FFFFFFF in this case) and add 1, and in this case it would overflow back to 0x80000000.
According to docs.oracle.com:-
byte: The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive). The byte data type can be useful for saving memory in large arrays, where the memory savings actually matters. They can also be used in place of int where their limits help to clarify your code; the fact that a variable's range is limited can serve as a form of documentation.
Byte - 8 bits
2^7 2^6 2^5 2^4 2^3 2^2 2^1 2^0
128 64 32 16 8 4 2 1)
Adding all these numbers we get a total of 255. Then how's the range which is -128 to 127 calculated. Is it hard-coded somewhere or there's some more technicality to this range?
Any suggestions would be appreciated.
Let's calculate range for 1 Byte
1 bit can take 0 or 1
1 Byte = 8 Bits
The first bit is used as a sign ( - or + )
then remaining bits are 7
so we can write 2^7 = 128 different numbers for one sign
we get 0 as a positive sign. then we have 128 numbers for the negative side,127 numbers for the positive side and 0 (zero)
so the range is -128 to 127 including 0
It is a signed type, meaning, it still has a range of 255 (as you have correctly calculated), but it starts at -128. So half the range is below zero, 1 possible number is = (zero) and the remaining 127 are above 0.
The first bit is the sign. (1 - minus, 0 - plus)
Formula for Range calculation is : -2^(n-1) to (2^(n-1)-1)
where n = no. of bits of primitive datatype.
Example:
For int datatype, n is 32, in short datatype, n is 16 etc.
So, int range will be: -2^(32-1) to (2^(32-1)-1)
By using the same formula Range of byte, short, float and double could be calculated.
That's because the first bit is used for the sign, since the data type is signed.
Please refer to http://en.wikipedia.org/wiki/Signed_number_representations
Since there is no unsigned primitive types in Java (like C or C#), is usual to cast it to a bigger type if you need to "overflow" the boundaries.
The last bit i.e. number 8 we are writing it 2^7 is a sign bit that decides negative or positive sign so it is 2^0 +2^1 +2^2 +2^3 +2^4 +2^5+ 2^6
Formula to calculate range in Java
-2(n-1) to +2(n-1)-1
Where n is the number of bit (1 byte= 8 bit)
So, for byte type range would be:
-2(8-1) to +2(8-1)-1
or, -2(7) to +2(7)-1
or, -128 to +127
it results from the standard representation of signed values as binary numbers. For a full description see http://en.wikipedia.org/wiki/Two%27s_complement.
-Rich
Let's calculate range for 1 Byte in C Langauge Datatype char
In case of char dataype lets consider -
1 Byte = 8 Bits
2^8 = 256
so we can write 2^8 = 256
In case of unsigned 0 to positive integers only.
4.1 In case of signed
we have 128 numbers for the negative side, 0 (zero) and 127 numbers for the positive side
so the range is -128 0 +127
Here 0 is taking one bit
Bit consists of 0’s and 1’s.byte normally consists of 8 bits.so the values can be calculated using the general formula which is given below,
no of values data type can have=2^n(2 power n), where n represents no of bits.
so the value of byte data type=2^8(i.e 1 byte=8 bits),here n=8
byte value=256
And it should be shared equal on both sides of zero ( half values at negative and half value at positive ). Hence the range for byte is from -128 to 127.
Range of data types
so now we came to know that how we are calculating the Range of the integer data types.This logic is applicable for all the integer data types.
The full details of all the data types are given below,
S.NO Data Type Bits Ranges values
1 boolean 1 – true or false(1 or 0)
2 byte 8 -128 to 127. 256(2^8)
3 short 16 -32,768 to 32,767 65,536(2^16)
4 int 32 -2^31 to (2^31)-1 2^32
5 long 64 Refer NOTE 2^64
6 float 32 Refer NOTE ———
7 double 64 Refer NOTE ———-
8 char 16 0 to 65,535 65,536(2^16)
As you know, the binary literal is a new feature that is introduced in Java 7:
int x = 0b1011;
System.out.println(x); // prints 11 as expected
But, when I tried to get the maximum number from the literal binary I got -1!!!
int x = 0b11111111111111111111111111111111;
System.out.println(x); // prints -1 !!!
Further Details:
System.out.println(Integer.MAX_VALUE);
System.out.println(0b1111111111111111111111111111111); // 31 bits
/* Both print 2147483647 */
/************************************************************************************/
System.out.println(Integer.MIN_VALUE);
System.out.println(0b10000000000000000000000000000000); // 32 bits (increment by 1)
/* Both print -2147483648 */
/************************************************************************************/
// And if you keep increasing the binary literal, its actual value
// will be decreased until you reach the maximum binary literal and
// its actual value will be -1.
System.out.println(0b11111111111111111111111111111111); // 32 bits
/* Prints -1 */
As you can see, the actual value of the literal binary (while the increment) jumps over from the maximum value of int to the minimum one and then keep decreasing till it reaches -1 which is the maximum value of the literal binary.
Is this a bug? or does it have something to do with signed/unsigned numbers?
You're using a signed integer. Bit 32 (the "first" one from the left) is the sign bit. It being 1 means it is a negative number, and 0 means positive. Two's complement is then performed to give the value of -1. Read about that here:
http://tfinley.net/notes/cps104/twoscomp.html
This is not a bug at all: since int is unsigned, all bits to 1 does mean -1.
The leftmost bit of a signed integer, in two's complement, is the sign bit. What you see is therefore expected.
Indeed this is a signed int so is 0xffff == 0b11111111111111111111111111111111 == -1.
This is not a positive number.
See also Wikipedia Two's complement.
Java uses 32 bit signed integers, and the max/min & overflow results you are seeing are valid.
For more information see: http://en.wikipedia.org/wiki/Integer_(computer_science)
Java's int uses 2's complement signed integers. This means the leftmost bit indicates a negative number. So
int x = 0b11111111111111111111111111111111;
// ^--- this bit
indicates the number is negative. The fact that all of the other bits are also 1 means that the number is (decimal) -1. See the link for details.