1

I have a REST API which provides values as decimal numbers and they need to be converted to strings using a map of bitshift operators:

EXCEPT DISABLED           1 << 0
EXCEPT MOTO               1 << 1
EXCEPT LOADING            1 << 2
EXCEPT COMMERCIAL         1 << 3

The max bitshift can get up to 28 (1<<28). The API provides a number, e.g. 262144, which I convert to binary (1000000000000000000) and then I deduce that the shift was 17. But how to write a function like this in Java?

Mukyuu
  • 6,436
  • 8
  • 40
  • 59
vrgrg
  • 566
  • 4
  • 17
  • I had an idea of converting to String bit representation using Integer.toBinaryString() and then count number of zeros, but it seems stupid solution. I wonder if there is a better way. – vrgrg Nov 24 '19 at 14:29
  • Is it always a 1 followed by that many 0's or could it look like 11000, say? If the former, my previous comment + a length will give you the shift. If not, I could write something that counts the 0's at the end, if any. If the former, a log base 2 ought to work, too, – Jeremy Kahan Nov 24 '19 at 14:29
  • so I guess I hd the same stupid solution :). There may be something slicker. – Jeremy Kahan Nov 24 '19 at 14:31
  • also, in your example, I think I'm missing something, because I count 18 zeroes. – Jeremy Kahan Nov 24 '19 at 14:38
  • Jeremy maybe I was counting wrong. Finally, my code in Kotlin is `val shift = Integer.toBinaryString(number).count { it == '0' }` – vrgrg Nov 24 '19 at 14:45
  • 1
    (int)Math.round(Math.log(number)/Math.log(2.0)) ought to do it, then. Assuming it's always a 1 followed by n zeroes. If it could look like 11 followed by n zeroes, this won't do. – Jeremy Kahan Nov 24 '19 at 14:51
  • Please specify whether multple bits can be set or not – MDK Nov 24 '19 at 14:59
  • As I look at this harder, int ought to do for your values, and so your approach of Integer.toBinaryString(givenNumber) and counting the zeroes at right would work. I have written a method to count zeroes at the right, but that hardly feels like an answer, since I'm sure you could too. But an answer is needed to the question of @MDK , before we can tell what an answer should look like. – Jeremy Kahan Nov 24 '19 at 15:03
  • @MDK I think it can only be be one 1, since the Kotlin (as I understand it) is counting all zeroes in the string, so I guess 1100 is different from 11000, but that seems unlikely since 10100 would get a wrong answer. If I'm right, the log calculation is ok, and more compact. – Jeremy Kahan Nov 24 '19 at 15:08
  • your displayed code does not follow java syntax. Please correct it or adjust the tags of your question. – Heri Nov 24 '19 at 15:50
  • @Heri I think the displayed code is how the value is generated, not in java. The task is to interpret it in java. – Jeremy Kahan Nov 24 '19 at 21:46
  • In java you define exactly these constants, there is nothing to interprete anymore afterwards. Thats why constants where invented for. – Heri Nov 25 '19 at 12:30
  • @heri yes, I was wondering if instead of doing a switch with (constants representing) 0 to 28 or individual comparisons with 0 to 28, one might as easily define constants for 2^0 to 2^28 and never do the conversion. – Jeremy Kahan Nov 25 '19 at 12:54

1 Answers1

0

I assume I understand the problem correctly, based on your equivalent code in Kotlin:

`val shift = Integer.toBinaryString(number).count { it == '0' }`,

that it suffices to count zeroes, not trailing zeroes.

I believe int suffices for the ranges you have. Thus your idea of doing:

int given = 262144;
String binaryString = Integer.toBinaryString(given);

will work.

int zeros = binaryString.length() - binaryString.replaceAll("0", "").length();

will give you the number of zeroes, which is your answer.

If so, though, and really all the zeroes are trailing, it seems likely (though I cannot be sure from the question) that we're always looking at a 1 followed by n zeroes. To find n, we could then also do:

(int)Math.round(Math.log(given)/Math.log(2.0))

to find the number of zeroes. Or for that matter, if we continue with the string approach, there would be no need to explicitly count the zeroes. Rather,

int zeros= binaryString.length()-1;

would suffice.

REVISION: There is something inelegant about all of the above. We are given an int which was 1 shifted left by any whole number from 0 to 28. We ought to be able to undo that without real number operations or strings, simply by shifting right until we get back to 1. Since our numbers are all > 0, we can use >>>, though >> (or /=2) would also do.

If the given int were given, the following puts the number of zeroes in count.

int temp = given;
int count = 0;
    while (temp>1){
        count++;
        temp=temp>>>1;
    }
Jeremy Kahan
  • 3,796
  • 1
  • 10
  • 23