Java BigInteger(byte[] val) - java

I am trying to understand how does the java.math.BigInteger.BigInteger(byte[] val) constructor work.
For example when I create a BigInteger instance from the byte array [1, 0], the corresponding string it creates is 256. Surely, the binary string 10 corresponds to value 2 in base 10. How does it convert it from 10 to 256? What am I missing?

Each byte in the array represents 8 bits, so [1, 0] is equivalent to 1 * 2^(8 * 1) + 0 * 2^(8 * 0), or, in binary: 00000001 00000000.
Beware that the BigInteger (byte[]) constructor also uses two's complement, so it's not just a matter of adding the unsigned numbers: the most significant bit will affect the sign.

It's effectively working in base-256, not base-2. So each position in the input array is worth 256 times more than the next position.
Pseudo-code:
x = 0;
for (i = 0; i < val.length - 1; i++) {
x = (x*256) + val[i];
}

Related

Adc Conversion quantization

double vDeltaRef, vPlusRef = 10, vMinusRef = 0, q, n, nExp = 3;
vDeltaRef = vPlusRef - vMinusRef;
n = Math.pow(2, nExp);
q = vDeltaRef / n;
System.out.println(q);
the result from the formula is 1.25v
this value:
How can I translate the obtained result
Since you know vPlusRef, vMinusRef and nExp, you can always calculate q (which is 1.25 in this case).
Then, to convert from digital to analog simply multiply the digital value with q. For example the 3-bit value 011, which is 3 in decimal, will be converted to 3.75 which is the lower bound of the required range 3.75 to 5.00.
Finally, to convert from analog to digital do:
int digitalValue = (int) Math.floor(analogValue / q);
For example an analog value of 8.19 would return 6, which is the 3-bit value 110.

How does this shuffling with Math rand work?

I saw this code to shuffle a list:
public static void shuffle(List<Integer> numbers) {
if(numbers == null || numbers.isEmpty()) return;
for(int i = 0; i < numbers.size(); ++i) {
int index = (int) (i + Math.random()*(numbers.size() - i));
swap(numbers, i, index);
}
}
The code seem to work but I don't understand this snippet:
int index = (int) (i + Math.random()*(numbers.size() - i));
Basically it is i + R*(n-i) but how does this ensure that: i) we won't get an out of bounds index or ii) I won't be changing the same element's i.e. index == i and the shuffle would not be that random?
Math.random() returns a uniform random number in the interval [0, 1), and numbers.size() - i, ideally, scales that number to the interval [0, numbers.size() - i). For example, if i is 2 and the size of the list is 5, a random number in the interval [0, 3) is chosen this way, in the ideal case. Finally, i is added to the number and the (int) cast discards the number's fractional part. Thus, in this example, a random integer in [2, 5) (that is, either 2, 3, or 4) is generated at random, so that at each iteration, the number at index X swaps with itself or a number that follows it.
However, there is an important subtlety here. Due to the nature of floating-point numbers and rounding error when scaling the number, in extremely rare cases the output of Math.random()*(numbers.size() - i) might be equal to numbers.size() - i, even if Math.random() outputs a number that excludes 1. rounding error can cause the idiom Math.random()*(numbers.size() - i) to bias some results over others. For example, this happens whenever 2^53 is not divisible by numbers.size() - i, since Math.random() uses java.util.Random under the hood, and its algorithm generates numbers with 53 bits of precision. Because of this, Math.random() is not the best way to write this code, and the code could have used a method specially made for generating random integers instead (such as the nextInt method of java.util.Random). See also this question and this question.
EDIT: As it turns out, the Math.random() * integer idiom does not produce the issue that it may return integer, at least when integer is any positive int and the round-to-nearest rounding mode is used as in Java. See this question.
Math.random() always returns a floating-point number between 0 (inclusive) and 1 (exclusive). So when you do Math.random()*(numbers.size() - i), the result will always be between 0 (inclusive) and n-i (exclusive).
Then you add i to it in i + Math.random()*(numbers.size() - i).
Now the result, as you can see, will be between i (inclusive) and n (exclusive).
After that, you are casting it to an int. When you cast a double to an int, you truncate it, so now the value of index will somewhere from ``iton - 1``` (inclusive for both).
Therefore, you will not have an ArrayIndexOutOfBoundsException, since it will always be at least 1 less than the size of the array.
However, the value of index could be equal to i, so yes, you are right in that a number could be swapped with itself and stay right there. That's perfectly fine.
You have a list of 1 to 50 ints.
So get a random value from 0 to 49 inclusive to index it.
say it is 30.
Get item at index 30.
Now replace item at index 30 with item at index 49.
Next time generate a number between 0 and 48 inclusive. 49 will never be reached and the number that was there occupies the slot of the last number used.
Continue this process until you've exhausted the list.
Note: that the expression (int)(Math.random() * n) will generate a random number between 0 and n-1 inclusive because Math.random generates a number between 0 and 1 exclusive.
Instead of using such a custom method, I recommend you use OOTB Collections.shuffle. Check this to understand the logic implemented for Collections.shuffle.
Analysis of your code:
Math.random() returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0.
Now, let's assume numbers.size() = 5 and dry run the for loop:
When i = 0, index = (int) (0 + Math.random()*(5 - 0)) = (int) (0 + 4.x) = 4
When i = 1, index = (int) (1 + Math.random()*(5 - 1)) = (int) (1 + 3.x) = 4
When i = 2, index = (int) (2 + Math.random()*(5 - 2)) = (int) (2 + 2.x) = 4
When i = 3, index = (int) (3 + Math.random()*(5 - 3)) = (int) (3 + 1.x) = 4
When i = 4, index = (int) (4 + Math.random()*(5 - 4)) = (int) (4 + 0.x) = 4
As you can see, the value of index will remain 4 in each iteration when numbers.size() = 5.
Your queries:
how does this ensure that: i) we won't get an out of bounds index
As already explained above using the dry run, it will never go out of bounds.
or ii) I won't be changing the same element's i.e. index == i and the
shuffle would not be that random?
swap(numbers, i, index); is swapping the element at index, i with the element at index, 4 each time when numbers.size() = 5. This is illustrated with the following example:
Let's say numbers = [1, 2, 3, 4, 5]
When i = 0, numbers will become [5, 2, 3, 4, 1]
When i = 1, numbers will become [5, 1, 3, 4, 2]
When i = 2, numbers will become [5, 1, 2, 4, 3]
When i = 3, numbers will become [5, 1, 2, 3, 4]
When i = 4, numbers will become [5, 1, 2, 3, 4]
int index = (int) (i + Math.random()*(numbers.size() - i)); - it is important to note that Math.random() will generate a number which belongs to <0;1). So it will never exceed the boundry as exclusive max will be: i + 1*(number.size() -i) = number.size
This point is valid, it can happen.

Binary arithmetic: why hash%n is equivalent to hash&(n-1)?

I have been studying Java HashMap source code, the part of it which decides in what bucket to put an object and saw this change in Java 7 (8) as compared to Java 6.
Additionally I conducted numerous experiments and both expressions yeild the same result:
hash % n
and
hash & (n - 1)
where n - the array length that must be power of 2.
I just cannot figure out why is it true? Is there any theorem or some math laws that prove these statement are equal? Basically I want to understand the inference and prove the equivalence of those two statements.
PS. If n is not a power of 2 number, the equivalence breaks immedeately.
If n is a power of two that mean its binary representation is 10000....,
n-1 for that matter is 1111111... with one less digit.
That means that binary &-ing with (n-1) preserves just exactly the number of bits in k that n-1 has set.
Example n = 8: 1000, n-1 = 7: 111
&-ing for example k = 201: 11001001
k % n = k & (n-1) = 11001001 & 111 = 001 = 1.
%-ing with a power of 2 means that in binary you just strip everything away that is above (including) the only set bit: for n = 8 that means stripping everything over (including) the 4th bit. And that is exactly what the &-ing does at well.
A side effect is that using & is commutative: hash & (n - 1) is equivalent to (n - 1) & hash which is not true for %, the jdk source code in many places uses the later, e.g. in getNode
Think about the bits in (n - 1) if n is a power of 2 (or ((1 << i) - 1), if you want to simplify the constraint on n):
If n is, say, 16 (= 1 << 4), then n - 1 is 15, and the bit representation of 15 and 16 (as 32-bit ints) are:
1 = 00000000000000000000000000000001 // Shift by 4 to get...
16 = 00000000000000000000000000010000 // Subtract 1 to get...
15 = 00000000000000000000000000001111
So just the lowest 4 bits are set in 15. If you & this with another int, it will only allow bits in the last 4 bits of that number to be set in the result, so the value will only be in the range 0-15, so it's like doing % 16.
However, note that this equivalence doesn't hold for a negative first operand:
System.out.println(-1 % 2); // -1
System.out.println(-1 & (2-1)); // 1
Ideone demo
The arithmetic rule for integer / and % is:
x*(y/x) + (y%x) = y
What about a negative hash -4 and a positive n 8?
8*0 + (-4%8) = -4
Hence modulo maintains the sign.
-4 % 8 = -4
-4 & 7 = 4
Or:
int t = hash%n;
if (t < 0) {
t += n;
}
assert t == (hash & (n-1));
So in the earlier java with %n hash had to be positive to begin with.
Now hash may be negative, more solid and better hashing.
So that was a sound reason for this subtle change in java source code.
Background:
2n is a 1 followed by n-1 0s (in binary).
2n - 1 is n-1 1s.
Hence for n being a positive power of 2, and some positive number h:
h % n == h & (n-1)
Another usage is to count bits in an int. The class Integer has just such a function.
int bits = 0;
while (x != 0) {
x &= x - 1;
++bits;
}

some thing wrong with array index in byte[]

I have string like this
String text = "f001050000000000003d61c1c1df400200c0000009181600ef014000003f20"
I converted it to bytes to loop through it as bytes
byte[] bytes = new BigInteger(text,16).toByteArray();
for (int i = 0; i < bytes.length; i++)
{
System.out.print(String.format("%02x ", bytes[i]));
}
But when I print array values it adds byte 00 at the beginning of the actual string!
It should start with f0 but it starts with 00!
When I start index with 1 this 00 disappear.
From where this 00 come!?
JavaDoc of BigInteger#toByteArray() states:
Returns a byte array containing the two's-complement
representation of this BigInteger. The byte array will be in big-endian byte-order: the most significant byte is in the zeroth element. The array will contain the minimum number of bytes required to represent this BigInteger, including at least one sign bit, which is (ceil((this.bitLength() + 1)/8)).[...]
As you have a positive number, the first bit will be zero in two's complement.
I think BigInteger is no good for this task. You need to parse your text yourself, it's not difficult
byte[] bytes = new byte[text.length() / 2];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) ((Character.digit(text.charAt(i * 2), 16) << 4) + Character.digit(text.charAt(i * 2 + 1), 16));
}
not that it also converts "0000f0..." correctly but BigInteger would truncate leading zeroes (normalize) because for BigInteger it is just a number

decomposing a value into powers of two

I need to implement a function which decomposes a value into powers of two using java.
e.g: 14= 8 + 4 + 2
I need to find the powers of two which the value gets decomposed. For the above example I need 2,3,1 as outputs. How could I implement that?
Take advantage of the binary representation that Java uses. I don't know what form you want the powers of 2 to take, but you can loop through the bits one at a time by shifting and bit-wise & with 1 to test each bit. Each 1 bit represents a power of 2 in the sum.
For instance:
List<Integer> powers = new ArrayList<Integer>();
n = . . .; // something > 0
int power = 0;
while (n != 0) {
if ((n & 1) != 0) {
powers.add(1 << power);
// or, if you just need the exponents:
// powers.add(power);
}
++power;
n >>>= 1;
}
As integers are already represented as powers of two and Java has a collections for a set of bits I would use these two.
public static void main(String[] args) {
System.out.println(bitsSet(14));
}
public static BitSet bitsSet(long num) {
BitSet bitSet = new BitSet();
for (int i = 0; i < 64; i++)
if (((num >>> i) & 1) != 0)
bitSet.set(i);
return bitSet;
}
prints
{1, 2, 3}
For this, you usually use bit-wise operations, namely the shift (<<,>>,>>>) and the bit-wise and (&) operator, because the internal representation of integers in computers already is binary, which is what you need.
In binary representation each integer value is a composition of powers of 2: 1, 2, 4, 8, 16, 32, ...
So, 14 in decimal is in binary 1110: 8 + 4 + 2 + 0.
If you're after some nice, generic algorithm, you may want to start decomposing decimal numbers into their powers of 10 and from there on extend your solution to other bases, like 2.
You could simply subtract 2 from the value and keep subtracting subsequent higher powers.
int x = 0;
int value = args[0];
for (i=0, (value - Math.pow(2, i)) >= 0, i++) {
value = value - Math.pow(2, i);
x++;
}
for (i=0, i<x, i++) {
System.out.println("addent: " + Math.pow(2, i);
}

Categories

Resources