Number of bits used in long - java - java

I want to know the number of bits really used in the long datatype in Java.
For instance:
long time = System.currentTimeMillis();
System.out.println(java.lang.Long.toHexString(time));
Output:
12c95165393
Here you can see it only has 11 hex digits which means only 44 bits out of 64 are utilized. 10 bits are still un-utilized. Is there a way to know at runtime how many bits are used OR to pad the remaining bits ?

Try Long.numberOfLeadingZeros():
long time = System.currentTimeMillis();
System.out.println(Long.numberOfLeadingZeros(time));
For used bits:
Long.SIZE - Long.numberOfLeadingZeros(time)

According to the API for 'toHexString', the leading zeros are stripped. http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Long.html#toHexString(long)
Therefore, you can't answer this question with the toHexString method.

You can format it with padding using String.format:
System.out.println(String.format("%016x", time));
If you want to know how many of the leading bits are unset you can either check the bits individually or you can right shift the number (with >>>, not >>) until it's zero.

There are just 11 hex digits in your example, because toHexString doesn't output leading zeroes.

Code:
String minBin=Long.toBinaryString(Long.MIN_VALUE),maxBin=Long.toBinaryString(Long.MAX_VALUE);
System.out.println("Number of bits in Min Long : "+minBin.length()+", Max Long : "+maxBin.length());
Output:
Number of bits in Min Long : 64, Max Long : 63 //1 extra bit in min long to represent sign

According to Java documentation, a long type variable always is 64 bits long.
If you mean to count how many bits there are between the least significant bit to the first most significant bit set to 1 then you can compute:
int usedBits( long time )
{
if( time != 0 )
return (int)( Math.log( time ) / Math.log( 2 ) ) + 1;
else
return 0;
}

The number of bits used are always 64. The number of bits set can be 0 and 64 (You should assume it can be anything else). The top bit set can be determined, but is highly unlikely to be useful. In short, you don't need to know.
If you want to print a fairly random number with a fixed width of digits or in hex, this is a printing/formatting issue and you can determine this with printf.

Related

How do I convert a short to an int without turning it into a negative in java

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? 😉

Reducing a long to an integer in java via bit shifting

My use case is this,
I wish to reduce an extremely long number like 97173329791011L to a smaller integer by shifting down and be able to get back the long number 97173329791011L from the smaller integer by shifting up .I have implemented a function called reduceLong to implement this as shown below
private int reduceLong(long reduceable) {
return (int) (reduceable >> 32);
}
However, I feel the function I have is in a way wrong as the result produced is incorrect. Here is the result from my console output when trying to reduce 97173329791011L to a smaller integer
Trying to reduce 97173329791011L
Result= 0
Your help would be greatly appreciated. Thanks alot.
The int datatype can hold all integral values in the range [-2^31, +2^31-1], inclusive. That's, in decimal, [-2147483648, 2147483647]. The total range covers 2^32 different numbers, and that makes sense because ints are 32 bits in memory. Just like you can't store an elephant in a matchbox, you can't store an infinite amount of data in 32 bits worth of data. You can store at most... 32 bits worth of data.
3706111600L is a long; it is (slightly) outside of the range of the int. In binary, it is:
11011100111001101100011001110000
How do you propose to store these 64 bits into a mere 32 bits? There is no general strategy here, and that is mathematically impossible to have: You can store exactly 2^64 different numbers in a long, and that's more unique values than 2^32, so whatever 'compression' algorithm you suggest, it cannot work except for at most 2^32 unique long values, which is only a very small number of them.
Separate from that, running your snippet: first, you do 11011100111001101100011001110000 >> 32, which gets rid of all of the bits. (there are exactly 32 bits there), hence why you get 0.
Perhaps you want this 'compression' algorithm: The 2^32 longs we decree as representable in this scheme are:
all the longs from 0 to 2^31-1, by mapping them to the same integer value, and then also another batch of 2^31 longs that immediately follow that, by mapping them bitwise, although, given that in java all numbers are signed, these then map to negative ints. All other long values (so all values above 2^32-1 and all negative longs) cannot be mapped (or if you try, they'd unmap to the wrong value).
If you want that, all you need to do:
int longToInt = (int) theLong;
long backToLong = 0xFFFFFFFFL & theLong;
Normally if you cast an int to a long it 'sign extends', filling the top 32 bits with 1s to represent the fact that your int is negative. The bitwise & operation clears the top 32 bits all back down to 0 and you're back to your original... IF the original long had 32 zero-bits at the top (which 3706111600L does).
Your test number is too small. Converted into Hexadecimal, 3706111600L is 0x00000000DCE6C670.
If you shift this number 32 bits to the right, you will lose the last 8 nibbles; your resulting number is 0x00000000L. Casted to int this value is still 0.

what happens in a &= -a with Java

I see this comment, but don't understand it.
Get its last set bit
diff &= -diff;
I tried
int a = 3 & -3; it returns 1.
int a = 2 & -2; it returns 2.
int a = 4 & -4; it returns 4.
int a = 5 & -5; it returns 1.
The comment would be better expressed as 'Get the least significant bit set'. To understand what is going on, you need to examine how negative numbers are represented in binary. The technique is called twos complement and works by starting with the positive representation of the number; you complement each bit (i.e. 1 -> 0 and 0 -> 1). You then add 1 to this number. In the example of 12:
00001100 12
11110011 complement
00000001 binary 1
11110100 add to complement to form twos complement negative
If you now AND the original value with the negative, you get
00000100
where the only bit set corresponds to the least significant bit set in the original pattern.
As the comment said, diff & -diff returns the value of the last bit that was set on diff. For example:
diff = 14
.... = 1110 (binary)
.... ^ last set bit
.... 10 is the last set bit
.... 10 in decimal is 2
Another example
diff = 24
.... = 11000 (binary)
.... ^ last set bit
.... 1000 is the last set bit
.... 1000 in decimal is 8
I would recommend reading the guidelines for how to ask a well formulated question. One recommendation I can personally give is to have one sentence at the end of your question that sums up exactly what it is you want to know.

Unexpected endless byte for loop

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" );
}

How to assign the largest n bit unsigned integer to a BigInteger in Java

I have a scenario where I'm working with large integers (e.g. 160 bit), and am trying to create the biggest possible unsigned integer that can be represented with an n bit number at run time. The exact value of n isn't known until the program has begun executing and read the value from a configuration file. So for example, n might be 160, or 128, or 192, etcetera...
Initially what I was thinking was something like:
BigInteger.valueOf((long)Math.pow(2, n));
but then I realized, the conversion to long that takes place sort of defeats the purpose, given that long is not comprised of enough bits in the first place to store the result. Any suggestions?
On the largest n-bit unsigned number
Let's first take a look at what this number is, mathematically.
In an unsigned binary representation, the largest n-bit number would have all bits set to 1. Let's take a look at some examples:
1(2)= 1 =21 - 1
11(2)= 3 =22 - 1
111(2)= 7 =23 - 1
:
1………1(2)=2n -1
   n
Note that this is analogous in decimal too. The largest 3 digit number is:
103- 1 = 1000 - 1 = 999
Thus, a subproblem of finding the largest n-bit unsigned number is computing 2n.
On computing powers of 2
Modern digital computers can compute powers of two efficiently, due to the following pattern:
20= 1(2)
21= 10(2)
22= 100(2)
23= 1000(2)
:
2n= 10………0(2)
       n
That is, 2n is simply a number having its bit n set to 1, and everything else set to 0 (remember that bits are numbered with zero-based indexing).
Solution
Putting the above together, we get this simple solution using BigInteger for our problem:
final int N = 5;
BigInteger twoToN = BigInteger.ZERO.setBit(N);
BigInteger maxNbits = twoToN.subtract(BigInteger.ONE);
System.out.println(maxNbits); // 31
If we were using long instead, then we can write something like this:
// for 64-bit signed long version, N < 64
System.out.println(
(1L << N) - 1
); // 31
There is no "set bit n" operation defined for long, so traditionally bit shifting is used instead. In fact, a BigInteger analog of this shifting technique is also possible:
System.out.println(
BigInteger.ONE.shiftLeft(N).subtract(BigInteger.ONE)
); // 31
See also
Wikipedia/Binary numeral system
Bit Twiddling Hacks
Additional BigInteger tips
BigInteger does have a pow method to compute non-negative power of any arbitrary number. If you're working in a modular ring, there are also modPow and modInverse.
You can individually setBit, flipBit or just testBit. You can get the overall bitCount, perform bitwise and with another BigInteger, and shiftLeft/shiftRight, etc.
As bonus, you can also compute the gcd or check if the number isProbablePrime.
ALWAYS remember that BigInteger, like String, is immutable. You can't invoke a method on an instance, and expect that instance to be modified. Instead, always assign the result returned by the method to your variables.
Just to clarify you want the largest n bit number (ie, the one will all n-bits set). If so, the following will do that for you:
BigInteger largestNBitInteger = BigInteger.ZERO.setBit(n).subtract(BigInteger.ONE);
Which is mathematically equivalent to 2^n - 1. Your question has how you do 2^n which is actually the smallest n+1 bit number. You can of course do that with:
BigInteger smallestNPlusOneBitInteger = BigInteger.ZERO.setBit(n);
I think there is pow method directly in BigInteger. You can use it for your purpose
The quickest way I can think of doing this is by using the constructor for BigInteger that takes a byte[].
BigInteger(byte[] val) constructs the BigInteger Object from an array of bytes. You are, however, dealing with bits, and so creating a byte[] that might consist of {127, 255, 255, 255, 255} for a 39 bit integer representing 2^40 - 1 might be a little tedious.
You could also use the constructor BigInteger(String val, int radix) - which might be readily more apparently what's going on in your code if you don't mind a performance hit for parsing a String. Then you could generate a string like val = "111111111111111111111111111111111111111" and then call BigInteger myInt = new BigInteger(val, 2); - resulting in the same 39 bit integer.
The first option will require some thinking about how to represent your number. That particular constructor expects a two's-compliment, big-endian representation of the number. The second will likely be marginally slower, but much clearer.
EDIT: Corrected numbers. I thought you meant represent 2^n, and didn't correctly read the largest value n bits could store.

Categories

Resources