I want to know the size of byte of my interger. Example :
public static void main(String[] args) throws IOException {
int a = 256;
System.out.println(nbBytes(a));
}
static byte nbBytes(int value) {
byte l = 0;
while (value != 0) {
value >>>= 8;
++l;
}
return l;
}
It works perfectly, But i want to optimize this calculation.
Have you a proposition ? :D
If you mean runtime performance, the following algorithm (which originally finds the highest set bit) is probably fastest. I've already modified it to return the number of bytes required to encode the integer argument:
private static final int[] DE_BRUIJN_BIT_POSITION_LUT = {
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};
public static int nbBytes2(int n) {
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8;
n |= n >> 16;
return DE_BRUIJN_BIT_POSITION_LUT[((n * 0x07C4ACDD) >> 27) & 0x1f] / 8 + 1;
}
Even if it looks more complicated, it does not have any loops or conditional processing, which allows optimal use of modern CPU pipelines.
Comparing the De Bruijn algorithm to your method, your method is ~4 times faster for inputs in the range 0x0-0xff (your method won't branch either). For inputs in the range 0x100-0xfff, my method is 19 times faster, for inputs 0x10000-0xffffff 28 times faster and for inputs >0x1000000 35 times faster. All numbers are valid for my hardware, on other computers it may of course differ.
In Java, an int is always a 32-bit, signed 2's-complement value. See, for instance, Section 2.3 of the Java Virtual Machine Specification.
If you want to know the minimum number of bits to store a particular value, you can use Integer.numberOfLeadingZeros to get that:
int bitsNeeded = 32 - Integer.numberOfLeadingZeros(value);
You can then round up to get the number of bytes needed.
If you're running an older version of Java that doesn't include this function, here's the 1.6 source for it:
public static int numberOfLeadingZeros(int i) {
if (i == 0)
return 32;
int n = 1;
if (i >>> 16 == 0) { n += 16; i <<= 16; }
if (i >>> 24 == 0) { n += 8; i <<= 8; }
if (i >>> 28 == 0) { n += 4; i <<= 4; }
if (i >>> 30 == 0) { n += 2; i <<= 2; }
n -= i >>> 31;
return n;
}
Whether this is more efficient than what you are already doing can only be determined, I think, by profiling. It will depend, as well, on the distribution of values that you expect to encounter.
If you only expect to deal with non-negative values, I would do this:
static byte nBytes(int value) {
if (value < (1 << 8)) return 1;
if (value < (1 << 16)) return 2;
if (value < (1 << 24)) return 3;
return 4;
}
This assumes that you require 1 byte to represent zero. To handle negative numbers, there are two logical choices:
Always return 4
Return the minimum number of bytes necessary to represent the value in 2's complement.
For the second case, I would do the following:
static byte nBytes(int value) {
if (value < 0) {
if (value > Integer.MIN_VALUE) {
value = -value;
if (value < (1 << 7)) return 1;
if (value < (1 << 15)) return 2;
if (value < (1 << 23)) return 3;
}
} else {
if (value < (1 << 8)) return 1;
if (value < (1 << 16)) return 2;
if (value < (1 << 24)) return 3;
}
return 4;
}
I don't know it this is more optimum, but another solution is something like (not tested):
return (byte)Math.ceil(Integer.toBinaryString(value).length()/8.0);
Related
In an infinite sequence of numbers [2, 5, 7, 22, 25, 27, 52, 55, 57, 72, 75, 77, 222, ...].
Given any number in this sequence get the immediate successor number.
Example:
Input Output
22 25
77 222
5 7
I have written the below logic to find the next number in a sequence.
public static int getNextNumInSequence(Integer sequenceCurrentNum) {
List<Integer> sequence = new ArrayList<>();
sequence.add(2);
sequence.add(5);
sequence.add(7);
if(sequence.get(0).equals(sequenceCurrentNum))
return sequence.get(1);
else if(sequence.get(1).equals(sequenceCurrentNum))
return sequence.get(2);
//This is not a finite loop, just for my testing i am running 300 iterations.
for(int i=0;i<300;i++) {
if(sequence.get(i).equals(sequenceCurrentNum)) {
return sequence.get(i+1);
}
int nextVal = sequence.get(i)*10;
Integer firstSeq = nextVal + sequence.get(0);
Integer secondSeq = nextVal + sequence.get(1);
Integer thirdSeq = nextVal + sequence.get(2);
sequence.add(firstSeq);
sequence.add(secondSeq);
sequence.add(thirdSeq);
if(firstSeq.equals(sequenceCurrentNum)) {
return secondSeq;
}else if(secondSeq.equals(sequenceCurrentNum)) {
return thirdSeq;
}
}
return 0;
}
My Approach:
I am constructing the entire sequence from the beginning
Then checking if we have reached to the given number in sequence.
Then return the successor.
Drawbacks:
I am constructing the entire sequence to reach to given number.
Memory wise and performance wise not suggestable.
Please help to understand, is there any better approach to get the successor without constructing entire sequence.
Example: Given 277755 should return 277757. (Without constructing the
entire sequnce)
Note: The sequence will not be provided as an input to our function. The only input we will be given is a valid number from the sequence.
Try this.
public static int getNextNumInSequence(Integer sequenceCurrentNum) {
int head = sequenceCurrentNum / 10;
int tail = sequenceCurrentNum % 10;
int headNext = head == 0 ? 2 : getNextNumInSequence(head);
if (headNext == 0) return 0;
switch (tail) {
case 2: return head * 10 + 5;
case 5: return head * 10 + 7;
case 7: return headNext * 10 + 2;
default: return 0;
}
}
public static void main(String[] args) {
for (int i = 0, k = 2; i < 20; ++i, k = getNextNumInSequence(k))
System.out.println(i + " : " + k);
}
output:
0 : 2
1 : 5
2 : 7
3 : 22
4 : 25
5 : 27
6 : 52
7 : 55
8 : 57
9 : 72
10 : 75
11 : 77
12 : 222
13 : 225
14 : 227
15 : 252
16 : 255
17 : 257
18 : 272
19 : 275
You can also get n-th number.
public static int getNumAtIndex(int n) {
int h = n / 3;
int t = n % 3;
return (h == 0 ? 0 : getNumAtIndex(h) * 10)
+ (t == 0 ? 2 : t == 1 ? 5 : 7);
}
test:
public static void main(String[] args) {
for (int i = 0; i < 10; ++i)
System.out.println(i + " : " + getNumAtIndex(i));
}
output:
0 : 2
1 : 5
2 : 7
3 : 52
4 : 55
5 : 57
6 : 72
7 : 75
8 : 77
9 : 522
First try to understand what is the logic behind the sequence. If you look carefully to the numbers, you may see counting in ternary base. To be more clear, let's replace '2' by '0', '5' by '1' and '7' by '2'. Then your sequence becomes:
(0, 1, 2, 10, 11, 12, 20, 21, 22, 100, 101, 102, ...)
It's just counting.
So the thing is to get the next number in ternary base, but using the digits 2, 5, 7. We must take care of digit 7: if we increment it, we get 2 but we have a carry for the digit before.
Here is a sample code:
public static Integer getNextNumInSequence(Integer number)
{
int digits[] = {2,5,7};
int idx_digits[] = {-1, -1, 0, -1, -1, 1, -1, 2, -1, -1};
Integer next_number = 0;
int carry = 1;
Integer pow10 = 1;
while (number>0)
{
int digit = number%10; //extract last digit
int idx_d = idx_digits[digit]; //get index of digit -- must be 0,1 or 2
if (idx_d==-1)
{
System.out.println("Invalid number");
return -1;
}
next_number += digits[(idx_d+carry)%3]*pow10; //compute next digit in sequence, taking care of the carry
carry = (digit==7)?1:0; //carry is 1 only if the current digit is 7
pow10 *= 10; //increment
number /= 10; //erase last digit
if (carry==0) //if no carry, we can stop the loop here, it's not useful to continue
{
break;
}
}
// at this point, either number>0 or carry==1
return ((carry>0)?2:number)*pow10+next_number; //final number is the digit sequence [2 if carry else number ; next_number]
}
You can solve this recursively.
If the final digit of the given number is 2 or 5, then it is easy: just change that final digit to 5 or 7 respectively.
Otherwise (when the final digit is 7), solve the problem without the last digit, and then append the digit 2 to that result. Of course, "without last digit" means an integer division by 10, and "appending" means multiplying by 10 and then adding the value of the digit.
Here is the function:
public static int getNextNumInSequence(Integer curr) {
if (curr % 10 == 2) return curr + 3;
if (curr % 10 == 5) return curr + 2;
if (curr == 7) return 22;
return getNextNumInSequence(curr / 10) * 10 + 2;
}
Note that one call has worst case time complexity of O(logn) where n is the value of the function argument, but amortised time complexity is O(1) per call.
To construct the list, you can simply do this:
List<Integer> list = Arrays.asList(2, 5, 7, 22, 25, 27, 52, 55, 57, 72, 75, 77, 222);
Note that there are cases where there is not successor. Here I will return null in those cases:
public static Integer getNextNumInSequence(List<Integer> list, Integer num) {
int pos = list.indexOf(num);
if (pos >= 0 && pos+1 < list.size()) {
return list.get(pos+1);
}
return null;
}
Note that I've added a parameter list so that you don't have to build the list each time you want to do a search.
In your example, the list is sorted; If it's always the case, you can use a binary search: Collections.binarySearch(list, num) instead of list.indexOf(num).
OK. If I understand correctly, you have three initial values:
static final int[] initial = {2, 5, 7};
and you can calculate the value at position ix like this:
private static int calculate(int ix) {
int div = ix/initial.length;
int rest = ix%initial.length;
int value = 0;
if (div > 0) {
value = 10*calculate(div-1);
}
return value+initial[rest];
}
To get the successor of num:
public static Integer getNextNumInSequence(int num) {
for (int i = 0; ; ++i) {
int cur = calculate(i);
if (cur == num) {
return calculate(i+1);
} else if (cur > num) {
return null;
}
}
}
Consider the following serie:
1, 1, 2, 2, 4, 8, 32, 256, ...
I wrote this method in Java:
public static int Fibmul(int n){
if (n == 1) return 1;
else if (n == 0) return 0;
else if (n < 0) return -1; // -1 means 'nil'
else {
n = Fibmul(n - 2) * Fibmul(n - 1);
}
return n;
}
To calculate the serie just multiply the last two positions of the elements to obtain the next element, E.g Fibmul(4) should return 4 and Fibmul(6) should return 32.
But this code is wrong an I don't have more ideas, I have clear the algorithm over the paper but I don't know how to implement it.
Can anybody help me?
Thanks in advance.
You're not going to get any higher numbers if your starting numbers are 0 and/or 1.
If your starting numbers are 1 and 2, you will get something like the sequence you described.
public static int Fibmul(int n){
if (n == 1) return 2;
else if (n == 0) return 1;
else if (n < 0) return -1; // -1 means 'nil'
else {
n = Fibmul(n - 2) * Fibmul(n - 1);
}
return n;
}
This will give
1, 2, 2, 4, 8, 32, ...
It cannot start with 1,1,2 if you want to follow the rule you stated, because 1*1 does not equal 2.
NB: Your sequence is actually the ordinary Fibonacci series but with each term used as a power of 2.
Fibonacci: 0, 1, 1, 2, 3, 5, 13, ...
Fibmul: 2**0, 2**1, 2**1, 2**2, 2**3, 2**5, 2**13, ...
You simply need an extra solution for when n == 2 because otherwise you'll remain stuck with 1, 1, 1, 1, 1, ...
public static int Fibmul(int n) {
if (n == 2)
return 2;
if (n == 1)
return 1;
else if (n == 0)
return 0;
else if (n < 0)
return -1; // -1 means 'nil'
return Fibmul(n - 2) * Fibmul(n - 1);
}
Testing it works as expected
Fibmul(0) = 0
Fibmul(1) = 1
Fibmul(2) = 2
Fibmul(3) = 2
Fibmul(4) = 4
Fibmul(5) = 8
Fibmul(6) = 32
Fibmul(7) = 256
Fibmul(8) = 8192
Fibmul(9) = 2097152
I think you are missing the 2 value. This should return 2, and the rest is fine:
else if (n == 2) return 2;
See here: https://code.sololearn.com/ca22A0a236a2
In my computer science class, I was given an algorithm to multiply two same-length binary numbers. I was instructed to convert it to multiply base 256 numbers and implement it in Java, but I can't seem to get the correct output and I don't know what I'm missing.
The algorithm that I was given:
MULTIPLY(U,V)
define array W[1..2n] for k = 1 to 2n
W[k] = 0 // Initialize result
for j=1 to n
c = 0 // Carry bit
for i = 1 to n
t = U[i]V[ j] + W [i+j] + c
W[i+j] = t mod 2 // lower bit
c= 𝑡/2 // upper bit
k = i+j
while k ≤ 2n and c ≠ 0 // propagate carry bit
t=W[k]+ c
W[k]=tmod2 // lower bit
c=𝑡/2 // upper bit
k++
return W
My attempt:
private static Byte[] bruteMultiply(Byte[] U, Byte[] V) {
Byte[] W = new Byte[U.length * 2];
for (int k = 0; k < W.length; k++) {
W[k] = 0;
}
for (int j = 0; j < U.length; j++) {
int c = 0;
for (int i = 0; i < U.length; i++) {
int t = (U[i] & 0xFF) * (V[j] & 0xFF) + (W[i + j] & 0xFF) + c;
W[i + j] = (byte) (t % 256);
c = t / 256;
}
int k = U.length + j;
while ((k < 2 * U.length) && (c != 0)) {
int t = (W[k] & 0xFF) + c;
W[k] = (byte) (t % 256);
c = t / 256;
k++;
}
}
return W;
}
When I feed it the arrays [197, 33, 151, 79] and [248, 164, 50, 235], I get [216, 234, 132, 91, 206, 122, 31, 73] when [191, 118, 251, 78, 251, 255, 83, 133] was expected.
I don't know what I'm missing or where I went wrong. Any suggestions or pointers would be helpful!
Hint: try to multiply [79, 151,33, 197] and [235, 50, 164, 248] with your code instead and compare the result to the target result.
I believe it is time for you to learn about the endianness. Generally your implementation looks OK but you use different endianness from the one in the example. Once you fix it, I think you'll get the correct answer.
P.S. I see no good reason to use Byte rather than byte in your array. This is another tricky difference that you probably should learn about.
So I'm trying to understand base64 encoding better and I came across this implementation on wikipedia
private static String base64Encode(byte[] in) {
StringBuffer out = new StringBuffer((in.length * 4) / 3);
int b;
for (int i = 0; i < in.length; i += 3) {
b = (in[i] & 0xFC) >> 2;
out.append(codes.charAt(b));
b = (in[i] & 0x03) << 4;
if (i + 1 < in.length) {
b |= (in[i + 1] & 0xF0) >> 4;
out.append(codes.charAt(b));
b = (in[i + 1] & 0x0F) << 2;
if (i + 2 < in.length) {
b |= (in[i + 2] & 0xC0) >> 6;
out.append(codes.charAt(b));
b = in[i + 2] & 0x3F;
out.append(codes.charAt(b));
} else {
out.append(codes.charAt(b));
out.append('=');
}
} else {
out.append(codes.charAt(b));
out.append("==");
}
}
return out.toString();
}
And I'm following along and I get to the line:
b = (in[i] & 0xFC) >> 2;
and I don't get it...why would you bitwise and 252 to a number then shift it right 2...wouldn't it be the same if you just shifted the byte itself without doing the bitwise operation? example:
b = in[i] >> 2;
Say my in[i] was the letter e...represented as 101 or in binary 01100101. If I shift that 2 to the right I get 011001 or 25. If I bitwise & it I get
01100101
11111100
--------
01100100
but then the shift is going to chop off the last 2 anyway...so why bother doing it?
Can somebody clarify for me please. Thanks.
IN in[i] >> 2, in[i] is converted to an int first. If it was a negative byte (with the high bit set) it will be converted to a negative int (with the now-highest 24 bits set as well).
In (in[i] & 0xFC) >> 2, in[i] is converted to an int as above, and then & 0xFC makes sure the extra bits are all reset to 0.
You're partially right, in that (in[i] & 0xFF) >> 2 would give the same result. & 0xFF is a common way to convert a byte to a non-negative int in the range 0 to 255.
The only way to know for sure why the original developer used 0xFC, and not 0xFF, is to ask them - but I speculate that it's to make it more obvious which bits are being used.
Given the byte array:
{255, 3, 5}
which is equivalent to:
{11111111, 00000011, 00000101}
I'd like to get the following result:
{23,22,21,20,19,18,17,16, 9,8, 2,0}
Which is an array of the indices of 1's in the input array.
What's the fastest way of doing this in Java?
Update:
I've chosen the fastest solution, which #aioobe's. Here are the test results of a pretty big data test:
#aioobe's way:
35s 289ms
35s 991ms
36s 174ms
#Martijn's way:
39s 274ms
39s 879ms
38s 684ms
Thanks you all! I appreciate your help.
What's the fastest way of doing this in Java?
Presumably by a 256 entry look-up table of the type int[][] in which lut[yourByte] equals the array of indexes for the ones in yourByte.
You then just do something like
for (int i = 0; i < bytes.length; i++)
for (int indexes : lut[bytes[i]])
appendToResult(indexes + (bytes.length - 1 - i) * 8);
Tested code (http://ideone.com/7NUjY):
public static List<Integer> getBitsIndices(byte[] input, boolean b)
{
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < input.length; ++i)
{
byte j = input[i];
for (int k = 7, bit = 1 << 7; k >= 0; --k, bit >>>= 1)
{
if ((j & bit) == bit == b)
{
list.add((input.length - i) * 8 - (8 - k));
}
}
}
return list;
}
Use it this way:
byte[] input = {(byte) 255, (byte) 3, (byte) 5};
System.out.println(getBitsIndices(input, true));
Output:
[23, 22, 21, 20, 19, 18, 17, 16, 9, 8, 2, 0]
I would (given {255, 3, 5} in integer) and always the last bit with 0x1 and then shift to the right.
Both operations are fast and have native CPU support.
Example:
pos, index = 0; res[];
00000101 AND 0x1 -> TRUE; res[index++] = pos++;
shift right
00000010 AND 0x1 -> FALSE; pos++;
shift right
... and so on.
I will make a test implementation this evening.