How are BigInteger stored - java

I need to generate 512 bit BigInts, but I'm not sure which of the two below is true:
512 bits means 512 digits of 1010101010...001010 which are then converted to the decimal it represents?
Or does it mean 512 digits of 0-9, so basicly a 512-digit number with digits ranging from 0-9? Something like 12414124124....54543=512 digits.

From sourcecode, they are stored in an int array
The magnitude of this BigInteger, in big-endian order: the zeroth element of this array is the most-significant int of the magnitude. The magnitude must be "minimal" in that the most-significant int (mag[0]) must be non-zero. This is necessary to ensure that there is exactly one representation for each BigInteger value. Note that this implies that the BigInteger zero has a zero-length mag array.
118
119 int[] mag;
120
121 // These "redundant fields" are initialized with recognizable nonsense
122 // values, and cached the first time they are needed (or never, if they
123 // aren't needed).
124

Conceptually, BigInteger converts an integer into arbitrary-length bit string, and then split the bit string by 4bytes. Then, each 4bytes result is assigned into each element in mag array:
BigInteger bi = new BigInteger("1234567890");
byte[] bytes = bi.toByteArray();
String rs = "";
for (byte b : bytes) {
String bs1 = Integer.toBinaryString(b & 0xff);
String bs2 = String.format("%8s", bs1).replace(' ', '0');
rs = rs + bs2 + " ";
}
System.out.println(bi.signum()); // 1
System.out.println(bi.bitLength()); // 31
System.out.println(rs); // 01001001 10010110 00000010 11010010
The final int signum is 1 (00000000 00000000 00000000 00000001).
The mag[0] in final int[] mag is 1234567890 (01001001 10010110 00000010 11010010). Yes, mag has one element only.
Let's represent more bigger integer:
BigInteger bi = new BigInteger("12345678901234567890");
byte[] bytes = bi.toByteArray();
String rs = "";
for (byte b : bytes) {
String bs1 = Integer.toBinaryString(b & 0xff);
String bs2 = String.format("%8s", bs1).replace(' ', '0');
rs = rs + bs2 + " ";
}
System.out.println(bi.signum()); // 1
System.out.println(bi.bitLength()); // 64
System.out.println(rs); // 00000000 10101011 01010100 10101001 10001100 11101011 00011111 00001010 11010010
The final int signum is 1 (00000000 00000000 00000000 00000001).
The mag[0] in final int[] mag is -1420514932 (10101011 01010100 10101001 10001100).
The mag[1] in final int[] mag is -350287150 (11101011 00011111 00001010 11010010).
When we instantiate an BigInteger instance with a negative integer:
BigInteger bi = new BigInteger("-1234567890");
byte[] bytes = bi.toByteArray();
String rs = "";
for (byte b : bytes) {
String bs1 = Integer.toBinaryString(b & 0xff);
String bs2 = String.format("%8s", bs1).replace(' ', '0');
rs = rs + bs2 + " ";
}
System.out.println(bi.signum()); // -1
System.out.println(bi.bitLength()); // 31
System.out.println(rs); // 10110110 01101001 11111101 00101110
The final int signum is -1 (11111111 11111111 11111111 11111111).
The mag[0] in final int[] mag is 1234567890 (01001001 10010110 00000010 11010010). Yes, mag stores number's magnitude.
When we call toByteArray(), BigInteger converts mag array's magnitude representation into 2's complement representation because signum is -1, meaning negative value. So, do not treat toByteArray as BigInteger's internal representation.
When we instantiate an BigInteger instance with zero:
BigInteger bi = new BigInteger("0");
byte[] bytes = bi.toByteArray();
String rs = "";
for (byte b : bytes) {
String bs1 = Integer.toBinaryString(b & 0xff);
String bs2 = String.format("%8s", bs1).replace(' ', '0');
rs = rs + bs2 + " ";
}
System.out.println(bi.signum()); // 0
System.out.println(bi.bitLength()); // 0
System.out.println(rs); // 00000000
The final int signum is 0 (00000000 00000000 00000000 00000000).
The final int[] mag has no element; zero-sized array. The magnitude must be "minimal" in that the most-significant int (mag[0]) must be non-zero. This is necessary to ensure that there is exactly one representation for each BigInteger value. Note that this implies that the BigInteger zero has a zero-length mag

Related

Reverse bits of a 32 bit unsigned integer

The problem is to reverse the bits of a 32 bit unsigned integer (since Java doesn't have unsigned integers we use long).
Here are two versions of my code. I have two concerns:
(1) why my 1st and 2nd solution don't return the same value (correct or not)
(2) where my 1st and 2nd solution went wrong in not getting the correct answer
//reverse(3) returns 0
public static long reverse(long a) {
long numBits = 32;
long finalResult = 0;
for(int i = 0; i < numBits; i++){
long ithBit = a & (1 << i);
finalResult = finalResult + ithBit * (1 << (numBits - i - 1));
}
return finalResult;
}
Second version:
//reverse(3) return 4294967296
public static long reverse(long a) {
long numBits = 32L;
long finalResult = 0L;
for(long i = 0L; i < numBits; i++){
long ithBit = a & (1L << i);
finalResult = finalResult + ithBit * (1L << (numBits - i - 1L));
}
return finalResult;
}
This code (the solution) returns the correct answer, however:
//reverse(3) returns 3221225472
public static long reverse(long A) {
long rev = 0;
for (int i = 0; i < 32; i++) {
rev <<= 1;
if ((A & (1 << i)) != 0)
rev |= 1;
}
return rev;
}
Thanks!
Let's have a look at your values as you iterate. For clarification, we'll have a look at the intermediate values, so we'll change code to:
int n = (1 << (numBits - i - 1));
long m = ithBit * n;
finalResult = finalResult + m;
Your starting value is 3:
a = 0000 0000 0000 0000 0000 0000 0000 0011
First loop iteration (i = 0):
ithBit = 00000000 00000000 00000000 00000001
n = 11111111 11111111 11111111 11111111 10000000 00000000 00000000 00000000
m = 11111111 11111111 11111111 11111111 10000000 00000000 00000000 00000000
finalResult = 11111111 11111111 11111111 11111111 10000000 00000000 00000000 00000000
Second loop iteration (i = 1):
ithBit = 00000000 00000000 00000000 00000010
n = 01000000 00000000 00000000 00000000
m = 10000000 00000000 00000000 00000000
finalResult = 00000000 00000000 00000000 00000000
As you can see, the first iterate sets n = 1 << 31, which is -2147483648. In your second version you do n = 1L << 31, which is 2147483648, and that's why your two versions give different results.
As you can also see, you definitely don't want to do the m = ithBit * n part.
Have a look at your number by printing them yourself, and you'll figure it out.
BTW, here's my version. If you have trouble understanding it, try printing the intermediate values to see what's going on.
public static long reverse4(long a) {
long rev = 0;
for (int i = 0; i < 32; i++, a >>= 1)
rev = (rev << 1) | (a & 1);
return rev;
}
since Java doesn't have unsigned integers we use long.
That's generally unecessary since all arithmetic operations except division and comparison result in identical bit patterns for unsigned and signed numbers in two's complement representation, which java uses. And for the latter two ops Integer.divideUnsigned(int, int) and Integer.compareUnsigned(int, int) are available.
The problem is to reverse the bits of a 32 bit unsigned integer
There's Integer.reverse(int)
Relevant docs, spending some time reading them is highly recommended.
Problem with your both examples is that the "i-th bit" isn't a 0 or 1 but rather masked off. In either case, the 31'th bit is 0x8000_0000. In the first case, this is an int, so it is negative, and when converted to a long it stays negative. In the second case it is already a long, so it stays positive. To fix it so it does what you intended, do:
ithBit = (a >>> i) & 1;
By the way, using long is silly; unsigned vs. signed makes no difference as long as you understand that there are two types of shifts in Java.
By the way, all three examples are terrible. If you are doing bit manipulation, you want speed, right? (Why else bother with bits?)
This is how to do it right (not mine, stolen from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits):
a = ((a >>> 1) & 0x55555555) | ((a & 0x55555555) << 1);
a = ((a >>> 2) & 0x33333333) | ((a & 0x33333333) << 2);
a = ((a >>> 4) & 0x0F0F0F0F) | ((a & 0x0F0F0F0F) << 4);
a = ((a >>> 8) & 0x00FF00FF) | ((a & 0x00FF00FF) << 8);
a = ( a >>> 16 ) | ( a << 16);
In both versions you have a logic problem here:
ithBit * (1 << (numBits - i - 1));
because the two numbers multiply to the same bit pattern of bit 31 (the 32nd) being set.
In version 1, the amount added is -2^31 if bit 0 is set because you're bit-shifting an int so the bit-shifted result is int which represents -2^31 as the high bit being set, or 2^31 for every other bit, which is possible due to the auto-cast to long of the result. You have two of each kind of bit (0 and non 0) so the result is zero.
Version 2 has the same problem, but without the negative int issue because you're bit shifting a long. Each bit that is 1 will add 2^31. The number 3 has 2 bits set, so your result is 2 * 2^31 (or 2^32) which is 4294967296.
To fix your logic, use version 2 but remove the multiply by ithBit.

Java bitwise operations return "wrong" value

---EDIT: I am not allowed to use any packages, or prewirtten methods. And no worries, i don't want you to make my "homework", i just need a little hint!---
I found these interesting Algorithms. I want to use the method bitwiseAdd. My problem is, that the left shift operator returns a value that is not binary...
I understand the algorithm, but i am quite a beginner. So here is the "program". I implemented extra outputs to find the issue. I think it must be the left shift operator. Here is the code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
class Addition1
{
public static int first;
public static int second;
public static void main(String args[]) throws Exception
{
BufferedReader userInput = new BufferedReader(newInputStreamReader(System.in));
System.out.println("Geben sie den ersten Summanden ein!");
first = Integer.parseInt(userInput.readLine());
System.out.println("Geben sie den zweiten Summanden ein!");
second = Integer.parseInt(userInput.readLine());
bitwiseAdd(first, second);
}
public static void bitwiseAdd(int n1, int n2)
{
int x = n1, y = n2;
int xor, and, temp;
and = x & y;
xor = x ^ y;
System.out.println("x: " + x);
System.out.println("y: " + y);
System.out.println("and: " + and);
System.out.println("xor: " + xor);
System.out.println("Schleife:");
while (and != 0)
{
and <<= 1;
System.out.println("and <<= 1: " + and);
temp = xor ^ and;
System.out.println("temp = xor ^ and: " + temp);
and &= xor;
System.out.println("and &= xor: " + and);
xor = temp;
System.out.println("xor = temp: " + xor);
}
System.out.println("Ergebnis: " + xor);
}
}
Here is the output (+annotations) of the program for n1= 1001 and n2=1101:
Geben sie den ersten Summanden ein! (means: type in first value)
1001
Geben sie den zweiten Summanden ein! (means: type in second value)
1101
x: 1001
y: 1101
and: 73 (java might interpret x and y as non binary)
xor: 1956
Schleife: (means: loop)
and <<= 1: 146
temp = xor ^ and: 1846
and &= xor: 128
xor = temp: 1846
and <<= 1: 256
temp = xor ^ and: 1590
and &= xor: 256
xor = temp: 1590
and <<= 1: 512
temp = xor ^ and: 1078
and &= xor: 512
xor = temp: 1078
and <<= 1: 1024
temp = xor ^ and: 54
and &= xor: 1024
xor = temp: 54
and <<= 1: 2048
temp = xor ^ and: 2102
and &= xor: 0
xor = temp: 2102
Ergebnis: 2102 (means: result)
I would be happy about any help! :)
Have a nice day,
Cortex
The values in your program were never interpreted as binary. You are actually adding the decimal values 1001 and 1101, and correctly summing them to 2102. Also, the binary representations of decimal 1001 and 1101 are
1001: 00000011 11101001
1101: 00000100 01001101
When anded, you get decimal 73:
73: 00000000 01001001
If you want to interpret those numbers as binary, use a radix of 2 in Integer.parseInt, for example:
first = Integer.parseInt(userInput.readLine(), 2);
To output a number in a binary format, use Integer.toBinaryString, for example:
System.out.println("Ergebnis: " + Integer.toBinaryString(xor));
You are trying to write a virtual machine inside a virtual machine inside the real machine, which might itself be a virtual machine. No wonder there is confusion.
You will need to represent you data as array of bool (or int or char etc).
bool [] operand1 = new bool [8];
bool [] operand2 = new bool [8];
bool [] leftShift (bool [] operand)
{
bool [] result = new bool [operand.length];
for (int i=8; i>1; i++)
{
result[i] = operand[i-1];
}
return result;
}
bool [] and (bool [] operand1, bool [] operand2)
{
int max, min;
if (operand1.length > operand2.length) {
max = operand1.length;
min = operand2.length;
}
else {
max = operand2.length;
min = operand1.length;
}
bool [] result = new bool [max];
for (int i = 0; i<min;i++)
{
result[i] = operand1[i] && operand2[i];
}
return result;
}
I used first = 1001; second = 1101; bitwiseAdd(first, second); in the main method, but still the program interprets these as decimal numbers (which is logical).
When you write a literal in a Java program, the syntax of the literal tells Java how to interpret it.
12345 // decimal
012345 // octal
0x1234 // hexadecimal
0b1001 // binary
There is no guesswork here. The syntax you use tells the Java compiler.
For more info: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
(The only slightly tricky thing is that a leading non-significant zero means that the number is octal not decimal. That is an regrettable (IMO) carry-over from the C programming language. It does trip up some people.)
Do you know how i can change that?
Yea ... if you want to express the numbers as binary in the source code, use binary literals.
The thing you need to get thoroughly into your head is that binary / octal / decimal / hexadecimal are all about getting numbers from or presenting numbers to the user (or programmer). Internally, they all turn into the same thing. The int type (and other integral types) are agnostic of decimal, binary and so on. There is only one type, and the arithmetic and bitwise operators on int have only one meaning.

Converting 5 bytes to an integer

I have some weird data that's stored in 5 bytes and I need to be able to convert it to an int to be able to manipulate it easier. I have some Python code (that was provided to me) that does this already, but I need to be able to have a solution in Java. I think my problem is now Python and Java differ in the way they store bytes.
Python (98% sure this works correctly):
def bin5(b,k):
""" Returns binary integer from bytes k,k+1,...,k+4 in b."""
b0 = b[k ]
b1 = b[k+1]
b2 = b[k+2]
b3 = b[k+3]
b4 = b[k+4]
if b0<0: b0 += 256
if b1<0: b1 += 256
if b2<0: b2 += 256
if b3<0: b3 += 256
if b4<0: b4 += 256
return b0*65536.0+b1*256.0+b2+b3/256.0+b4/65536.0
Java attempt:
// Returns binary integer from bytes k,k+1,...,k+4 in b.
private static int bin5(byte[] b, int k) {
byte b0 = b[k];
byte b1 = b[k + 1];
byte b2 = b[k + 2];
byte b3 = b[k + 3];
byte b4 = b[k + 4];
return (int)(b0 * 65536.0 + b1 * 256.0 + b2 + b3 / 256.0 + b4 / 65536.0);
}
I'm certain the problem is in the last return statement of the Java code. Also, it will work for some byte arrays, but not for others. I can't find a reason for this behavior.
EDIT: Example:
If the Python code reads the bytes: 0 11 -72 0 0 for b0 thru b5 respectfully, it will change the -72 to 184 and then calculate the value 3000.0 based on the equation above. Based on the survey/data parameters, this value is correct.
My intuition says that the python code IS faulty for some values. One such value is when it reads a values 0 -127 -66 0 0 (b0 thru b5 respectfully) which turns into: 0 129 190 0 0 and then the value 33214 is output by the conversion. This is impossible based on the survey/data parameters. BUT there is a possibility that this could be a faulty data point.
EDIT 2:
0 13 9 0 0 should return 3337 (and does in the python code). However under Java, it returns 3593.
You could do
private static double bin5(byte[] b, int k) {
int b0 = b[k] & 0xFF; // treat as unsigned byte
int b1 = b[k + 1] & 0xFF;
int b2 = b[k + 2] & 0xFF;
int b3 = b[k + 3] & 0xFF;
int b4 = b[k + 4] & 0xFF;
return (b0 * 65536 + b1 * 256 + b2 + b3 / 256.0 + b4 / 65536.0);
}
As powers of 2 can be represented exactly with double you won't get any rounding error.
This code is strange; it does not return an integer at all but a float...
Anyway, the Java equivalent of the python code is something like this (note: NO bounds checking is done at all):
private static double bin5(final byte[] b, final int k)
{
final ByteBuffer buf = ByteBuffer.allocate(8);
buf.position(3);
buf.put(b, k, 5);
buf.rewind();
final long l = buf.getLong();
return (double) l / 65536.0;
}
EDIT: if the last two elements of the byte array at offset k are always 0 (which it looks like they are) then you can replace from buf.rewind() onwards with:
buf.position(2);
return (double) buf.getInt();

count leading zeros (clz) or number of leading zeros (nlz) in Java

I need int 32 in binary as 00100000 or int 127 in binary 0111 1111.
The variant Integer.toBinaryString returns results only from 1.
If I build the for loop this way:
for (int i= 32; i <= 127; i + +) {
System.out.println (i);
System.out.println (Integer.toBinaryString (i));
}
And from binary numbers I need the number of leading zeros (count leading zeros (clz) or number of leading zeros (nlz)) I really meant the exact number of 0, such ex: at 00100000 -> 2 and at 0111 1111 - > 1
How about
int lz = Integer.numberOfLeadingZeros(i & 0xFF) - 24;
int tz = Integer.numberOfLeadingZeros(i | 0x100); // max is 8.
Count the number of leading zeros as follows:
int lz = 8;
while (i)
{
lz--;
i >>>= 1;
}
Of course, this supposes the number doesn't exceed 255, otherwise, you would get negative results.
Efficient solution is int ans = 8-(log2(x)+1)
you can calculate log2(x)= logy (x) / logy (2)
public class UtilsInt {
int leadingZerosInt(int i) {
return leadingZeros(i,Integer.SIZE);
}
/**
* use recursion to find occurence of first set bit
* rotate right by one bit & adjust complement
* check if rotate value is not zero if so stop counting/recursion
* #param i - integer to check
* #param maxBitsCount - size of type (in this case int)
* if we want to check only for:
* positive values we can set this to Integer.SIZE / 2
* (as int is signed in java - positive values are in L16 bits)
*/
private synchronized int leadingZeros(int i, int maxBitsCount) {
try {
logger.debug("checking if bit: "+ maxBitsCount
+ " is set | " + UtilsInt.intToString(i,8));
return (i >>>= 1) != 0 ? leadingZeros(i, --maxBitsCount) : maxBitsCount;
} finally {
if(i==0) logger.debug("bits in this integer from: " + --maxBitsCount
+ " up to last are not set (i'm counting from msb->lsb)");
}
}
}
test statement:
int leadingZeros = new UtilsInt.leadingZerosInt(255); // 8
test output:
checking if bit: 32 is set |00000000 00000000 00000000 11111111
checking if bit: 31 is set |00000000 00000000 00000000 01111111
checking if bit: 30 is set |00000000 00000000 00000000 00111111
checking if bit: 29 is set |00000000 00000000 00000000 00011111
checking if bit: 28 is set |00000000 00000000 00000000 00001111
checking if bit: 27 is set |00000000 00000000 00000000 00000111
checking if bit: 26 is set |00000000 00000000 00000000 00000011
checking if bit: 25 is set |00000000 00000000 00000000 00000001
bits in this integer from: 24 up to last are not set (i'm counting from msb->lsb)

Java create a byte by XOR 2 bytes

I have 2 byte arrays, each containing 4 bytes (byte1[], byte2[]) and I want to XOR them to create a new 4 byte array (byte3[]) how would I do this?
(or even do each byte at a time then put them into the new array)
You need to convert them to integers (no loss, primitive widening), do the XOR, then convert the resulting int back to a byte using a bit mask.
// convert to ints and xor
int one = (int)byte1[0];
int two = (int)byte2[0];
int xor = one ^ two;
// convert back to byte
byte b = (byte)(0xff & xor);
Example
String a = "10101010";
String b = "01010101";
String expected = "11111111"; // expected result of a ^ b
int aInt = Integer.parseInt(a, 2);
int bInt = Integer.parseInt(b, 2);
int xorInt = Integer.parseInt(expected, 2);
byte aByte = (byte)aInt;
byte bByte = (byte)bInt;
byte xorByte = (byte)xorInt;
// conversion routine compacted into single line
byte xor = (byte)(0xff & ((int)aByte) ^ ((int)bByte));
System.out.println(xorInt + " // 11111111 as integer");
System.out.println(xorByte + " // 11111111 as byte");
System.out.println(aInt + " // a as integer");
System.out.println(bInt + " // b as integer");
System.out.println((aInt ^ bInt) + " // a ^ b as integers");
System.out.println(aByte + " // a as byte");
System.out.println(bByte + " // b as byte");
System.out.println(xor + " // a ^ b as bytes");
Prints the following output
255 // 11111111 as integer
-1 // 11111111 as byte
170 // a as integer
85 // b as integer
255 // a ^ b as integers
-86 // a as byte
85 // b as byte
-1 // a ^ b as bytes
You can use the xor operation on bytes. It's the caret (^).
Example:
byte3[0] = (byte) (byte1[0] ^ byte2[0]);
This will work for equal or different size byte array as well.
/** Return XOR of two byte array of different or same size. */
public static byte[] xor(byte[] data1, byte[] data2) {
// make data2 the largest...
if (data1.length > data2.length) {
byte[] tmp = data2;
data2 = data1;
data1 = tmp;
}
for (int i = 0; i < data1.length; i++) {
data2[i] ^= data1[i];
}
return data2;
}
Java has a XOR operator in the form of ^. Just XOR each byte with each subsequent byte and put them in the new array.

Categories

Resources