Java BigInteger pow with an int base - java

I'm probably missing something and kinda rusted out this sort of thing, I was wondering what is the best way to implement 2^Biginteger into a variable? I'm sure it's a simple question. This is to aid in figuring out a 2-pseudoprime. (Basically to see if 2^N-1 = 1 mod N or not).

So if I understand you, you want to do something like this:
BigInteger bigExp = ... some really large value
BigInteger pow = BigInteger.valueOf(2).pow(bigExp);
Unfortunately, that won't work.
As you noted, there is no pow overload that takes a BigInteger argument. And when you think about it, such a method would be problematic.
The value of 2N is a value with N significant bits when represented in binary. If is larger than will fit into an int, then that means N is 231 or more. Or converting to bytes, that is 228 bytes or 0.25 Gigabytes. For a single number.
That isn't impossibly large. It should be possible to represent numbers that big, even in a 32 bit JVM. The problem is that any BigInteger arithmetic operation is liable to generate another one of these monsters. Just creating a number of this size is going to copy 0.25 Gigabytes, and operations like multiplication and division ... which are O(N^2) for N bit numbers ... are going to take "forever".
Having said that, there would be ways to generate numbers that size. For example, you could allocate a huge byte array (which default initializes to zero), set the appropriate byte to contain a 1 bit, and then use BigInteger(byte[]) to construct the monster number.

As #StephenC points out, these numbers will be too unwieldy.
But
to see if 2^N-1 = 1 mod N or not
You don't need to calculate 2^X. You can calculate 2^X mod N. A much smaller number.
BigInteger.valueOf(2).modPow(n.subtract(ONE), n);

Related

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.

Java HashMap array size

I am reading the implementation details of Java 8 HashMap, can anyone let me know why Java HashMap initial array size is 16 specifically? What is so special about 16? And why is it the power of two always? Thanks
The reason why powers of 2 appear everywhere is because when expressing numbers in binary (as they are in circuits), certain math operations on powers of 2 are simpler and faster to perform (just think about how easy math with powers of 10 are with the decimal system we use). For example, multication is not a very efficient process in computers - circuits use a method similar to the one you use when multiplying two numbers each with multiple digits. Multiplying or dividing by a power of 2 requires the computer to just move bits to the left for multiplying or the right for dividing.
And as for why 16 for HashMap? 10 is a commonly used default for dynamically growing structures (arbitrarily chosen), and 16 is not far off - but is a power of 2.
You can do modulus very efficiently for a power of 2. n % d = n & (d-1) when d is a power of 2, and modulus is used to determine which index an item maps to in the internal array - which means it occurs very often in a Java HashMap. Modulus requires division, which is also much less efficient than using the bitwise and operator. You can convince yourself of this by reading a book on Digital Logic.
The reason why bitwise and works this way for powers of two is because every power of 2 is expressed as a single bit set to 1. Let's say that bit is t. When you subtract 1 from a power of 2, you set every bit below t to 1, and every bit above t (as well as t) to 0. Bitwise and therefore saves the values of all bits below position t from the number n (as expressed above), and sets the rest to 0.
But how does that help us? Remember that when dividing by a power of 10, you can count the number of zeroes following the 1, and take that number of digits starting from the least significant of the dividend in order to find the remainder. Example: 637989 % 1000 = 989. A similar property applies to binary numbers with only one bit set to 1, and the rest set to 0. Example: 100101 % 001000 = 000101
There's one more thing about choosing the hash & (n - 1) versus modulo and that is negative hashes. hashcode is of type int, which of course can be negative. modulo on a negative number (in Java) is negative also, while & is not.
Another reason is that you want all of the slots in the array to be equally likely to be used. Since hash() is evenly distributed over 32 bits, if the array size didn't divide into the hash space, then there would be a remainder causing lower indexes to have a slightly higher chance of being used. Ideally, not just the hash, but (hash() % array_size) is random and evenly distributed.
But this only really matters for data with a small hash range (like a byte or character).

How to get table size 2^32 in java

I have to get in java protected final static int [] SIEVE = new int [ 1 << 32 ];
But i cant force java to that.
Max sieve what i get is 2^26 i need 2^32 to end my homework. I tried with mask but i need to have SIEVE[n] = k where min{k: k|n & k >2}.
EDIT
I need to find Factor numbers from 2 to 2^63-1 using Sieve and sieve must have information that P[n]= is smallest prime with divide n. I know that with sieve i can Factorise number to 2^52. But how do that exercises with holding on to the content.
EDIT x2 problem solved
You can't. A Java array can have at most 2^31 - 1 elements because the size of an array has to fit in a signed 32-bit integer.
This applies whether you run on a 32 bit or 64 bit JVM.
I suspect that you are missing something in your homework. Is the requirement to be able to find all primes less than 2^32 or something? If that is the case, they expect you to treat each int of the int[] as an array of 32 bits. And you need an array of only 2^25 ints to do that ... if my arithmetic is right.
A BitSet is another good alternative.
A LinkedList<Integer> is a poor alternative. It uses roughly 8 times the memory that an array of the same size would, and the performance of get(int) is going to be horribly slow for a long list ... assuming that you use it in the obvious fashion.
If you want something that can efficiently use as much memory as you can configure your JVM to use, then you should use an int[][] i.e. an array of arrays of integers, with the int[] instances being as large as you can make them.
I need to find Factor numbers from 2 to 2^63-1 using Sieve and sieve must have information that P[n]= is smallest prime with divide n. I know that with sieve i can Factorise number to 2^52. But how do that exercises with holding on to the content.
I'm not really sure I understand you. To factorize a number in the region of 2^64, you only need prime numbers up to 2^32 ... not 2^52. (The square root of 2^64 is 2^32 and a non-prime number must have a prime factor that is less than or equal to its square root.)
It sounds like you are trying to sieve more numbers than you need to.
If you really need to store that much data in memory, try using java.util.LinkedList collection instead.
However, there's a fundamental flaw in your algorithm if you need to store 16GB of data in memory.
If you're talking about Sieve of Eratosthenes and you need to store all primes < 2^32 in an array, you still wouldn't need an array of size 2^32. I'd suggest you use java.util.BitSet to find the primes and either iterate and print or store them in a LinkedList as required.

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.

How do you raise a Java BigInteger to the power of a BigInteger without doing modular arithmetic?

I'm doing some large integer computing, and I need to raise a BigInteger to the power of another BigInteger. The .pow() method does what I want, but takes an int value as an argument. The .modPow method takes a BigInteger as an argument, but I do not want an answer congruent to the value I'm trying to compute.
My BigInteger exponent is too large to be represented as an int, can someone suggest a way to work around this limitation?
You shouldn't try to calculate the power of an extremely large number with another extremely large number. The resulting number would use huge amounts of memory. If you calculate a.pow(b) it will have approximately log(a)*b digits. If b is too large to fit in an integer then for even quite small values of a the result will have several billion digits.
Try to rethink what you are trying to achieve and how to achieve it without doing this operation.
The practical solution is to convert the exponent from a BigInteger to an int.
If you cannot do this because the exponent is too large, your algorithm is unimplementable. The resulting number would almost certainly be too large to represent as a BigInteger. (A BigInteger uses an array of bytes to represent the number, and the maximum size of a Java array is 2**31 - 1 elements no matter how large the heap is.) And even if you implemented a "BiggerInteger" class that would represent the number, you would soon be pushing the limits of the physical memory size of your machine. (And the time taken to do calculate N.pow(M) would be ... NP-tricky ... O((MlogN)^M) I think).
Of course, if the number you are taking the power of is 0, 1 or -1, then the result will easily fit in a BigInteger. But in those cases, there are better ways to calculate the power :-).
You can't find the the value of "Java BigInteger to-the-power BigInteger" because according to JavaDoc "BigInteger must support values in the range -2^Integer.MAX_VALUE (exclusive) to +2^Integer.MAX_VALUE (exclusive) and may support values outside of that range."
So, Java BigInteger does not support anything above 2^Integer.MAX_VALUE. Tha's why pow method does not take any argument above int.
Hope this answer helps.
Assuming we've already accepted the fact that we shouldn't do this for the reasons outlined in all of the previous answers, here's a working solution that can be used for testing purposes only:
Exponent greater than or equal to 0
BigInteger pow(BigInteger base, BigInteger exponent) {
BigInteger result = BigInteger.ONE;
for (BigInteger i = BigInteger.ZERO; i.compareTo(exponent) != 0; i = i.add(BigInteger.ONE)) {
result = result.multiply(base);
}
return result;
}
This will work for both positive and negative bases. You might want to handle 0 to the power of 0 according to your needs, since that's technically undefined.
Exponent can be both positive or negative
BigDecimal allIntegersPow(BigInteger base, BigInteger exponent) {
if (BigInteger.ZERO.compareTo(exponent) > 0) {
return BigDecimal.ONE.divide(new BigDecimal(pow(base, exponent.negate())), 2, RoundingMode.HALF_UP);
}
return new BigDecimal(pow(base, exponent));
}
This uses the first method to return a BigDecimal with 2 decimal places, you can define the scale and rounding mode as per your needs.
Again, you should not do this in a real-life, production-level system.

Categories

Resources