Usage of BigIntegers and to the power off i - java

I found out longs wont cut it, as the numbers I'm calculating are to huge to fit. I'm struggling with the concept of BigInts.
Lets say I have the following equation to perform.
int p = 11549
int n = 252817
The equation is as follows.. : ( number * p )^ (to the power of i)%n .
With longs I just did :
long number;
long p;
long n;
long temp;
long total;
for (int i=0; i<6;i++) {
temp = numer*Math.pow(p,i);
total += temp;
}
total %= n;
But when i use Math.pow on I the numbers get to huge to use this method, and I need to use BigIntegers. I Just dont understand how I can do it. Right now I got this : (Missing the % until i can figure out the power off statement.)
long temp;
long p;
BigInteger opphoyd;
BigInteger mod;
for (int i=0;i<6;i++) {
temp = number * p;
opphoyd = BigInteger.valueOf(temp);
mod = BigInteger.valueOf(i);
mod.add(opphoyd.pow(i));
mod.add(opphoyd);
System.out.println(mod);
}
But its not working at all, could anyone point me in the right direction?

BigInteger's add method (and most of the other methods) does not modify the BigInteger it is called on. Instead it returns a new BigInteger.
So you would need to do:
BigInteger sum = mod.add(opphoyd);
Take a look at the javadocs, it will be very helpful when working with BigInteger.
long temp;
long p;
BigInteger opphoyd;
BigInteger mod;
for( int i = 0; i < 6; i++ ) {
temp = number * p;
opphoyd = BigInteger.valueOf(temp);
mod = BigInteger.valueOf(i);
BigInteger sum = mod.add( opphoyd.pow(i));
sum = sum.add(opphoyd);
System.out.println( sum );
}

Related

I want to replace BigInteger for loop in Stream Api

Want to replace BigInteger loop in Java Stream API.
Below code, I have to modify in java8 using Stream API. Because of performance concerns.
My question what would be the best practice to change below code into best performance.
public BigInteger getSum(BigInteger n, BigInteger c) {
BigInteger sum = BigInteger.ZERO;
for (BigInteger i = BigInteger.ZERO; i.compareTo(n) < 0; i=i.add(BigInteger.ONE)) {
sum = sum.add(calculateProduct(i, i.subtract(BigInteger.ONE), c));
}
return sum;
}
private BigInteger calculateProduct(BigInteger i, BigInteger j, BigInteger c) {
if (j.compareTo(BigInteger.ZERO) < 0) return BigInteger.ZERO;
if (j.compareTo(BigInteger.ZERO) == 0) return BigInteger.ONE;
if ((i.subtract(j).compareTo(c)) <= 0){
return j.add(BigInteger.ONE).multiply(calculateProduct(i, j.subtract(BigInteger.ONE), c));
}else
return BigInteger.ONE;
}
It looks like you are adding up products of sliding window of width c. If you want to improve performance, get rid of recursion and avoid recomputing the entire product. Use the product computed in the previous step: multiply it by the number entering the window and divide by the number exiting the window. Division is slower but it will pay off for larger values of c.
Finally, while I will keep your method signature, you really only need BigInteger as return.
BigInteger getSum(BigInteger n, BigInteger c) {
BigInteger p = BigInteger.ONE, sum = BigInteger.ZERO;
for (BigInteger x = BigInteger.ONE; x.compareTo(n) < 0; x = x.add(BigInteger.ONE)) {
p = p.multiply(x);
if (x.compareTo(c) > 0) {
p = p.divide(x.subtract(c));
}
sum = sum.add(p);
}
return sum;
}
If you want to speed it up further, you can use a bit of math to avoid having to divide at every step. Your sum can be broken up into s1 = sum[1,c) x! and s2 = sum[c,n) x!/(x-c)!. The second sum equals n!/(n-c-1)!/(c+1) (follows from hockey stick identity). The method below does not handle the trivial case of c >=n. I will leave that to you.
private static BigInteger fasterSum(BigInteger n, BigInteger c) {
assert c.compareTo(n) < 0;
BigInteger sum = ZERO, p = ONE;
for (BigInteger x = ONE; x.compareTo(c) < 0; x = x.add(ONE)) {
p = p.multiply(x);
sum = sum.add(p);
}
// sum[c,n) x!/(x-c)! = n!/(n-c-1)!/(c+1)
p = ONE;
for (BigInteger x = n.subtract(c); x.compareTo(n) <= 0; x = x.add(ONE)) {
p = p.multiply(x);
}
sum = sum.add(p.divide(c.add(ONE)));
return sum;
}
So I assume you want to add a list of BigInteger:
You can do that by using a reduce operation (https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html)
List<BigInteger> list = new ArrayList<>();
list.add(BigInteger.valueOf(5));
list.add(BigInteger.valueOf(1));
list.add(BigInteger.valueOf(3));
list.add(BigInteger.valueOf(10));
list.add(BigInteger.valueOf(2));
BigInteger sum = list.stream().reduce((x, y) -> x.add(y)).get();
System.out.println(sum);
That will calculate the sum, an equivalent would be:
BigInteger sum = list.stream().reduce(BigInteger::add).get();
You could also write an own Collector that is reusable and extract the reduce operation to there:
public static Collector<BigInteger, ?, BigInteger> calculateSum() {
return Collectors.reducing(BigInteger.ZERO, BigInteger::add);
}
and then do:
BigInteger sum = list.stream().collect(calculateSum());

Large Powers without using Big Integer

I had a problem where i had to calculate sum of large powers of numbers in an array and return the result.For example arr=[10,12,34,56] then output should be
10^1+12^2+34^3+56^4.Here the output could be very large so we were asked to take a mod of 10^10+11 on the output and then return it.I did it easily in python but in java initially i used BigInteger and got tle for half the test cases so i thought of using Long and then calculating power using modular exponential but then i got the wrong output to be precise all in negative as it obviously exceeded the limit.
Here is my code using Long and Modular exponential.
static long power(long x, long y, long p)
{
long res = 1; // Initialize result
x = x % p; // Update x if it is more than or
// equal to p
while (y > 0)
{
// If y is odd, multiply x with result
if ((y & 1)==1)
res = (res*x) % p;
// y must be even now
y = y>>1; // y = y/2
x = (x*x) % p;
}
return res;
}
static long solve(int[] a) {
// Write your code here
Long[] arr = new Long[a.length];
for (int i = 0; i < a.length; i++) {
arr[i] = setBits(new Long(a[i]));
}
Long Mod = new Long("10000000011");
Long c = new Long(0);
for (int i = 0; i < arr.length; i++) {
c += power(arr[i], new Long(i + 1),Mod) % Mod;
}
return c % Mod;
}
static long setBits(Long a) {
Long count = new Long(0);
while (a > 0) {
a &= (a - 1);
count++;
}
return count;
}
Then i also tried Binary Exponentiation but nothing worked for me.How do i achieve this without using big integer and as easily as i got it in python
You have added an extra zero the value of mod, it should be 1000000011.
Hope this will solve it

How to get precise Math.exp() in j2me?

I am using j2me and I need to get quite precise exp() for values up to 4.
Problem with the j2me is that it's Math library doesn't have pow() and exp() method. To solve this, I just used this method to implement pow():
public static double pow(double num1, double num2) {
double result = 1;
for (int i = 0; i < num2; i++)
result *= num1;
return result;
}
This enabled me to have exp functionality by using setting e as constant (2.718281828459045) and calling pow:
double calculation = (20.386 - (5132.000 / (t + 273.15)));
System.out.println("calc: " + pow(2.71,calculation));
calculation = pow(2.7182818284590452,calculation) * 1.33;
My problem is that result is quite inaccurate, for example if I compare math.exp and my pow method for number 3,75, results are like this:
Pow function returns: 54.5980031309658
Math function returns: 42.52108200006278
So I would need advice, how to implement exp functionality in j2me environment with highest precision possible.
I helped my self with bharath answer in this question: How to get the power of a number in J2ME
Since exp method is just pow, where we use Euler's number for the first argument, I used bharath method:
public double powSqrt(double x, double y)
{
int den = 1024, num = (int)(y*den), iterations = 10;
double n = Double.MAX_VALUE;
while( n >= Double.MAX_VALUE && iterations > 1)
{
n = x;
for( int i=1; i < num; i++ )n*=x;
if( n >= Double.MAX_VALUE )
{
iterations--;
den = (int)(den / 2);
num = (int)(y*den);
}
}
for( int i = 0; i <iterations; i++ )n = Math.sqrt(n);
return n;
}
Method call:
calculation = powSqrt(2.7182818284590452,calculation) * 1.33;
Result is almost as good as Math.pow() method.
PS:
I don't know if this is duplicated thread, if so you can delete it.

Java: avoiding factorial overflow

I'm supposed to optimize the following code so that it calculates the central binomial coefficient up to the max value of integer (up to n = 16).
public static int factorial(int n)
{
int result= 1;
for(int i = 2; i <= n; i++) result *= i;
return result;
}
public static int centralbinom(int n)
{
return factorial(2*n) / (factorial(n) * factorial(n));
}
Naturally I get an overflow for every n > 6.
How do I 'break down' the factorial function so that doesn't has to deal with big numbers such as 2n = 2*16 = 32 ?
Or is there a better way to calculate the central binomial coefficient?
Here are several optimizations that you can do in addition to using BigIntegers that may reduce your calculations, in most of you cases overflow that you may be having in your program.
Since you need factorial(n) at least two time. Calculate it once and store it in a variable.
Factorial(2*n) has factorial(n) in it. Since you have already calculated factorial(n) before all you need to do is calculate till factorial(2n....n) and then multiply factorial(n) to it. Here's one way how that can be done.
//Pseudocode
//find factorial of n given I know already till k
int findFactorial(n, k) {
int result = 1
for i n to 1
if(i==k)
break;
result = result * n;
return result
}
//factorial(2*n) = facorial(n, k) * factorial(k)
This will reduce your calculations a lot and in case if you expect your program not to have an overflow, you can go away with BigIntegers.
If you need a factorial of big number, you have to use BigInteger class to calculate result:
public static BigInteger factorial(int n) {
BigInteger result = BigInteger.ONE;
for (int i = 2; i <= n; ++i) {
result = result.multiply(BigInteger.valueOf(i));
}
return result;
}
If the central binomial coefficient of 17 is greater than the integer max, and you only need to compute it for 17 numbers, then the obvious solution is a lookup table. Create a 17-element array containing the central binomial coefficient for n = 0 to 16. I think you'll find this solution is extremely efficient.
You can find a list of them here. http://oeis.org/A000984
Just compress your factorial by gamma.
set gamma to 10 is good enough
public static double factorial(int n, double gamma)
{
double result= 1;
double gammaInv = 1.0/gamma;
for(int i = 2; i <= n; i++) result *= pow(i,gammaInv);
return result;
}
public static int centralbinom(int n, double gamma)
{
return pow(factorial(2*n,gamma) /
(factorial(n,gamma) * factorial(n),gamma),
gamma);
}

Error in my Java Fibonacci sequence?

public class Arrays {
public static void main(String[] args){
long Fib[] = new long[100];
Fib[0] = 1;
Fib[1] = 1;
int i = 0;
while(i <= 100){
Fib[i+2]= Fib[i] + Fib[i+1];
System.out.println(Fib[i]);
i++;
}
}
}
I used this to find Fibonacci numbers, but it starts giving me strange readings at around the 94th term. Anyone care to explain? I'm totally new to Java, so please don't hate if it's something obvious.
Here's some snippets of the error'ed output, but everything else looks fine:
832040
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 100
1346269
...
63245986
at Arrays.main(102334155
Arrays.java:8)
165580141
...
4660046610375530309
7540113804746346429
-6246583658587674878
1293530146158671551
-4953053512429003327
-3659523366270331776
-8612576878699335103
6174643828739884737
Here is the solution. you are trying to access 102th element i + 2 where i = 100
Fib[0] = 1;
Fib[1] = 1;
int i = 2;
while(i < 100){
Fib[i]= Fib[i-1] + Fib[i-2];
System.out.println(Fib[i]);
i++;
}
Furthermore, 97th Fibonacci number exceeds long range where it is between -9,223,372,036,854,775,808 and 9,223,372,036,854,775,807. 97th Fibonacci is 83,621,143,489,848,410,000 you should use BigInteger instead of long
Below code prints until 1000 digit fibonacci number.
BigInteger first = new BigInteger("0");
BigInteger second = new BigInteger("1");
BigInteger temp;// = new BigInteger("0");
int counter = 1;
while(numberOfDigits(second) < 1000)
{
temp = new BigInteger(second.toString());
second = second.add(first);
first = new BigInteger(temp.toString());
counter++;
}
System.out.print(counter);
}
public static int numberOfDigits(BigInteger number)
{
return number.toString().length();
}
java.lang.ArrayIndexOutOfBoundsException: 100
means that the array index 100 does not exist.
`long Fib[] = new long[100];`
creates indexes 0 - 99
When i reaches 98, Fib[i+2] will evaluate to Fib[100], which will throw an ArrayIndexOutOfBoundsException because Fib has length 100 and arrays are zero-index (as you demonstrated by assigning Fib[0]).
Also, you are getting negative results because the results are too large to fit into a long, so they are overflowing. The maximum value of a long is 9,223,372,036,854,775,807, and the 93rd Fibonacci number is the first one to exceed this with a value of 12,200,160,415,121,876,738.
There's no need in arrays to generate Fibonacci sequence.
Another trick is to use double (long is too small for 100th Fibonacci number)
double penultimate = 1; // <- long is not long enough ;) use double or BigInteger
double ultimate = 1;
System.out.println(penultimate);
for (int i = 1; i < 100; ++i) {
System.out.println(ultimate);
double h = penultimate + ultimate;
penultimate = ultimate;
ultimate = h;
}
Also, you can iterate loop 98 times to get the series.
It will give you last element of Fib[100] = 6174643828739884737 .
long Fib[] = new long[100];
Fib[0] = 1;
Fib[1] = 1;
int i = 0;
while(i < 98){
Fib[i+2]= Fib[i] + Fib[i+1];
System.out.println(Fib[i]);
i++;
}

Categories

Resources