Get the maximum value for a BigInteger with n bits - java

I want to compare two multiplication methods implemented in Java which use shift operations on big numbers. Thus I need sufficiently large BigIntegers.
Since I want to compare them bit-wise, what would be the best approach to generate BigIntegers with n bits which are fully used in the multiplication operation.
My approach so far is this:
byte[] bits = new byte[bitLength];
BigInteger number = new BigInteger(bits).flipBit(bitLength);

How about this:
import java.math.BigInteger;
public class Test
{
public static void main(String[] args)
{
int bits = 3;
BigInteger value = BigInteger.ZERO
.setBit(bits)
.subtract(BigInteger.ONE);
System.out.println(value); // Prints 7 == 111 in binary
}
}
In other words, set the bit which is one higher than you want, then subtract one to get a value which uses all the lower bits.

Related

how to find number of digits in factorial of 42?

factorial of 42 is going beyond the final limit of long data type in java. that's why I can't find digits.
42!
The factorial of 42 is of 51 digits while the max limit of long datatype in Java is 9,223,372,036,854,775,807 i.e only 20 digits. But don't worry, Java has a Big Integer class to store large numbers such as 100!. But it's a bit slower than primitive data types such as int, long etc because it stores integers in the form of arrays. There are many ways to implement the Big Integer class but here's the most used way. This code calculates the factorial of 42 and prints the same-
// Java program to find large factorials using BigInteger
import java.math.BigInteger;
public class Factorial
{
// Returns Factorial of N
static BigInteger factorial(int N)
{
BigInteger fact = new BigInteger("1"); // Or BigInteger.ONE
// Multiply f with 2, 3, ...N
for (int i = 2; i <= N; i++)
fact = fact.multiply(BigInteger.valueOf(i));
return fact;
}
public static void main(String args[])
{
int N = 42;
System.out.println(factorial(N));
}
}
Output:
1405006117752879898543142606244511569936384000000000
Explanation
We have to import the Big Integer class, which is stored in java.math package. I have named my file Factorial.java, so my class name is Factorial.
In this method, I've created a function, if you want the code without function, just comment below. Now in this syntax-
BigInteger f = new BigInteger("1");
I've assigned fact as Big integer which is equal to 1. In the for loop,
i value is set to 2 s 1*1=1.
fact = fact.multiply(BigInteger.valueOf(i));
The above syntax is for the multiplication of Big integers. This multiplies the Biginteger fact by i.
Have a look at this GeeksforGeeks article- https://www.geeksforgeeks.org/biginteger-class-in-java/
If you only care about the number of digits, I would recommend taking a more mathematical approach. There are ways to compute this number without actually computing the factorial itself. This would not require so big a variable and would be a lot faster.
You could think it this way:
Digits(n!) = floor(log10(n!)) + 1 = floor(log10(n * (n - 1) * ... * 1)) + 1 =floor(\sum_{i = 1}^{n}log10(i)) + 1
A picture of this expression: expression
This would still require iteration, but it deals with much smaller numbers.
If you still want O(1) complexity for this task, you can go with a pretty good approximation I've just tried.
Digits(n!) ~ floor(\int_{1}^{x}log10(x) dx) + 1 = floor(\frac{-x + x*ln(x) + 1}{ln(10)}) + 1
Another image of this formula: approximate expression
Of course, the latter is no absolutely exact since we are now integrating a continuous function. However, it will probably be worth implementing.
Digits(42!) = floor(50.37...) + 1 = 50 + 1 = 51

BigInteger power of a BigDecimal in Java

I tried to get the power of a double value where the exponent is very large (Java BigInteger can contain it (the exponent), for example: 10^30)
That is, I want to find something like 1.75^(10^30) or 1.23^(34234534534222).if the output is too large modify it by getting the modulus by a prime like 10^9+7.
If I want to find a power of an Integer I can use BigInteger.modPow() method which take BigInteger arguments:
( BigInteger modPow(BigInteger exponent, BigInteger m) )
As far as i can go this is what i got in Java
new BigDecimal("1.5").pow(1000); // .pow() can get only integers as a parameter , but i want to pass a big number like a BigInteger
I cannot find an equivalent for that (BigInteger.modPow()) in java for BigDecimal
, or i'm missing that.
Are there any ways to do that - Calculate a large power of a floating point number (a Decimal)?
Example of input and output :
Input : num // or 1.5 or any decimal number. can be an integer also.
exponent : exp // big integer or a Long value
output : num^exp // num to ther power exp
i.e like calculating 1.23^(34234534534222)
if the output is too large modify it by getting the modulus by a prime like 10^9+7
There is a Math.BigDecimal implementation of core mathematical functions which has:
static java.math.BigDecimal powRound(java.math.BigDecimal x, java.math.BigInteger n)
Raise to an integer power and round.
which seems exactly what you need. The fact that there is an external library for it denotes that there is no core implementation of a method like this in java.Math.
As a side note I can say that if your input is considerably small in terms of decimal places (thus no irrational) just like 1.5 you can transform it in 15/10 and do
(15^BigInteger)/(10^BigInteger)
with the modPow(BigInteger exponent, BigInteger m) of BigInteger. This obviously raises the complexity and the numbers to calculate.
There are several caveats. As Gábor Bakos pointed out, the resulting value would most likely contain too many digits to even be represented as a BigDecimal.
Additionally, these number of digits grows quickly, so computing something like 2.034234534534222 is completely out of scope in terms of storage (and, as I assume, in terms of required time).
You mentioned that the value may be computed modulo a large prime when it becomes "too large". Although you did not say what exactly this means, this won't necessarily help you here, because using modulo will not truncate the decimal places. You'll somehow have to limit the precision in which the computation takes place.
However, the most simple implementation using exponentiation by squaring could roughly look like this:
import java.math.BigDecimal;
import java.math.BigInteger;
public class BigDecimalPow {
public static void main(String[] args) {
BigDecimal b = new BigDecimal(1.5);
BigInteger e = new BigInteger("325322");
BigDecimal result = pow(b, e);
System.out.println("Done "+result.scale());
System.out.println(result);
}
/**
* Computes d to the power of e
* #param b The value
* #param e The exponent
* #return The power
*/
private static BigDecimal pow(BigDecimal b, BigInteger e) {
BigDecimal result = BigDecimal.ONE;
BigDecimal p = b;
int skipped = 0;
while (e.compareTo(BigInteger.ZERO) > 0) {
if (e.and(BigInteger.ONE).equals(BigInteger.ONE)) {
if (skipped > 0) {
if (skipped > 29) {
p = pow(p, BigInteger.ONE.shiftLeft(skipped));
} else {
p = p.pow(1 << skipped);
}
skipped = 0;
}
result = result.multiply(p);
}
skipped++;
e = e.shiftRight(1);
System.out.println(e);
}
return result;
}
}
Note: The implementation above is really simple. There most likely is a solution that is more efficient for some cases, or uses the modulo operation to support "larger" numbers. But you simply can not represent (potentially) 34234534534222 decimal places unless you have 34 terabytes of RAM and a JVM with long addressing, so I doubt that there will be a solution that satisfies the requirements that you stated until now - but would upvote+bounty anyone who proved me wrong...

How can I examine each digit of a BigInteger in Java?

How can I examine each digit (System.out.println() each digit, for instance) of a BigInteger in Java? Is there any other way other than converting it to a string?
Straight-forward code prints digits from the last towards the first:
private static void printDigits(BigInteger num) {
BigInteger[] resultAndRemainder;
do {
resultAndRemainder = num.divideAndRemainder(BigInteger.TEN);
System.out.println(Math.abs(resultAndRemainder[1].intValue()));
num = resultAndRemainder[0];
} while (num.compareTo(BigInteger.ZERO) != 0);
}
The BigInteger API docs do not appear to provide any functionality as such. Moreover, the numbers are quite likely not represented in base 10 (since it would be quite inefficient). So it is most likely that the only way to inspect the decimal digits of a BigInteger is to look at its string representation.
You could of course use basic math to calculate each digit. Especially the method divideAndRemainder might help here. But I doubt, that this is more efficient than converting to a String and examing the characters. BigInteger math is more expensive than plain int or long math after all.
I think the only way you could do it is converting it into a String and verify each char. Here is an example:
BigInteger bigInteger = new BigInteger("123");
String bigIntegerValue = bigInteger.toString();
for(int i = 0; i < bigIntegerValue.length(); i++) {
System.out.println(bigIntegerValue.charAt(i));
}
Maybe you can try to examine each bit in your biginteger using BitSet like this,
BitSet bitSet = BitSet.valueOf(bigInteger.toByteArray());
It seems pretty simple what you need to do get each digit of a number.
create a loop that tracks if you number is greater then ten and then preform a mod 10 operation on it and then divide by ten.
while (num >10)
{
System.out.println(num%10);
num = num/10;
}

How to avoid java.lang.OutOfMemoryError?

I have two simple java codes.The first one defines constant power as power = a.pow(b);
import java.math.BigInteger;
public class FermatOne
{
public static void main(String[] args)
{
BigInteger a = new BigInteger ("2");
BigInteger k = new BigInteger ("15");
BigInteger c = new BigInteger ("1");
int b = 332192810;
BigInteger n = new BigInteger ("2");
BigInteger power;
power = a.pow(b);
BigInteger exponent;
exponent = k.multiply(power);
BigInteger mod;
mod = exponent.add(c);
BigInteger result = n.modPow(exponent,mod);
System.out.println("Result is ==> " + result);
}
}
The second one defines constant power as power = BigInteger.ONE.shiftLeft(b)
import java.math.BigInteger;
public class FermatOne
{
public static void main(String[] args)
{
BigInteger k = new BigInteger ("15");
BigInteger c = new BigInteger ("1");
int b = 332192810;
BigInteger n = new BigInteger ("2");
BigInteger power;
power = BigInteger.ONE.shiftLeft(b);
BigInteger exponent;
exponent = k.multiply(power);
BigInteger mod;
mod = exponent.add(c);
BigInteger result = n.modPow(exponent,mod);
System.out.println("Result is ==> " + result);
}
}
Setting the memory flag -Xmx1024m in the command line the first code works fine , but for the second code I am getting error : java.lang.OutOfMemoryError :Java heap space
My question : What should I change in the second code to avoid java.lang.OutOfMemoryError ?
You're trying to calculate a number like 2 ^ (15 * 2 ^ 332192809). I don't know if you could even fit such a number in the universe!! Or maybe, the answer is simply... 42 ? ;-)
On a more serious note, you'll really have trouble, calculating this number. Encoded in bits, 15 * 2 ^ 332192810 would require almost a gigabyte by itself. Then raising 2 to that power again, I don't want to know...
On a more serious note, when you dig into the implementation of java.math.BigInteger, I think that you just run into such an error faster with the left shift, as that is implemented much more efficiently, than the power method. Having said this, have you tried to force garbage collection in your code, using System.gc()?
UPDATE: My original reasoning might've been wrong. 2 ^ 332192809 can be calculated with 1GB. And the overall result might be "modded" efficiently by java.math.BigInteger, although I believe that this calculation might take a while...
It's just a guess, but BigInteger.ONE.shiftLeft(332192810); will internally create an int array of length x + 10381025. Since an int is 4 bytes big you'll get about 40 mega bytes of data just for that one call. I assume the other calls copy that data around and thus you get that high a memory consumption.

Hashing to uniformly distribute value over a large range

I want to devise an algorithm which takes a set of values and distributes it uniformly over a much larger range. eg. i have 1000 values and want to distribute them over a range of value 2^16.
Also, the input values can change continuously and i need to keep parsing each input value through the hash function so that it gets distributed uniformly over my output range.
What hashing algorithm should i use for this?
I am writing the code in Java.
If you're just hashing integers, here's one way.
public class Hasho {
private static final Long LARGE_PRIME = 948701839L;
private static final Long LARGE_PRIME2 = 6920451961L;
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println(i + " -> " + hash(i));
}
}
public static int hash(int i) {
// Spread out values
long scaled = (long) i * LARGE_PRIME;
// Fill in the lower bits
long shifted = scaled + LARGE_PRIME2;
// Add to the lower 32 bits the upper bits which would be lost in
// the conversion to an int.
long filled = shifted + ((shifted & 0xFFFFFFFF00000000L) >> 32);
// Pare it down to 31 bits in this case. Replace 7 with F if you
// want negative numbers or leave off the `& mask` part entirely.
int masked = (int) (filled & 0x7FFFFFFF);
return masked;
}
}
This is merely an example to show how it can be done. There is some serious math in a professional quality hash function.
I'm sure this has a name, but this is what we used to do with ISAM files back in the dark ages
Increment a number eg 16001
Reverse the String ie. 10061 and you have your hash
You might want to reverse the string bitwise
This produces a nice even spread. we used to use it with job numbers so that you could retrieve the job fairly easily, so if you have a 'magic number' candidate this can be useful.

Categories

Resources