Optimise arithmetic operations on very large numbers - java

I want to compute the function H(n)
where
H(0)=0;
H(i)=H(i-1)×A+Ci mod B;
10<=A,B<=10^15;
C is an array of n elements
The following code takes too much time...any better way of doing this?
public BigInteger H(int no) {
if(no>0) {
bi=H(no-1);
bi=bi.multiply(BigInteger.valueOf(A));
bi=bi.add(BigInteger.valueOf(c[no-1]));
bi=bi.remainder(BigInteger.valueOf(B));
return bi;
}
return BigInteger.ZERO;
}

Try using a dynamic programming approach. Rather than using recursion, loop starting at the initial case H(0) and moving up from there. Example:
public static BigInteger H(BigInteger[] c, int no, BigInteger A, BigInteger B) {
if (c.length < no - 1) {
throw new IllegalArgumentException("no is too large");
}
BigInteger bi = BigInteger.ZERO; // Initial case H(0) = 0
for (int i = 1; i <= no; i++) { // From H(1) -> H(no)
bi = bi.multiply(A).add(c[i - 1]).remainder(B);
}
return bi;
}

Try not using the remainder every iteration, it uses division which is VERY slow.
You should also not use BigInteger.valueOf() every iteration. Only create A and B as BigIntegers one time and save them, there is no need for doing it more times.

Yeah, welcome to the world of BigIntegers.
One thing I remember is that you can do two paths for this:
1) A slow path with BigIntegers
2) A fast path with double primitive types when both the arguments are less than Max Double.
That should pump up the speed a little bit.
Tell us here how it went and post times if you can. This is really interesting.

Related

Converting a binary string to integer using a basic mathematical operator

Main:
public class Main{
public static void main(String[] args){
System.out.println(Convert.BtoI("10001"));
System.out.println(Convert.BtoI("101010101"));
}
}
Class:
public class Convert{
public static int BtoI(String num){
Integer i= Integer.parseInt(num,2);
return i;
}
}
So I was working on converters, I was struggling as I am new to java and my friend suggested using integer method, which works. However, which method would be most efficient to convert using the basic operators (e.g. logical, arithmetic etc.)
.... my friend suggested using integer method, which works.
Correct:
it works, and
it is the best way.
However, which method would be most efficient to convert using the basic operators (e.g. logical, arithmetic etc.)
If you are new to Java, you should not be obsessing over the efficiency of your code. You don't have the intuition.
You probably shouldn't optimize this it even if you are experienced. In most cases, small scale efficiencies are irrelevant, and you are better off using a profiler to validate your intuition about what is important before you start to optimize.
Even if this is a performance hotspot in your application, the Integer.parseint code has (no doubt) already been well optimized. There is little chance that you could do significantly better using "primitive" operations. (Under the hood, the methods will most likely already be doing the same thing as you would be doing.)
If you are just asking this because you are curious, take a look at the source code for the Integer class.
If you want to use basic arithmetic to convert binary numbers to integers then you can replace the BtoI() method within the class Convert with the following code.
public static int BtoI(String num){
int number = 0; // declare the number to store the result
int power = 0; // declare power variable
// loop from end to start of the binary number
for(int i = num.length()-1; i >= 0; i--)
{
// check if the number encountered is 1
/// if yes then do 2^Power and add to the result
if(num.charAt(i) == '1')
number += Math.pow(2, power);
// increment the power to use in next iteration
power++;
}
// return the number
return number;
}
Normal calculation is performed in above code to get the result. e.g.
101 => 1*2^2 + 0 + 1*2^0 = 5

How to transfer an outside recursion program into a non-recursive form (using stack not CPS)?

there are many questions about how to convert recursive to non-recursive, and I also can convert some recursive programs to non-recursive form
note: I use an generalized way (user defined Stack), because I think it is easy to understand, and I use Java, so can not use GOTO keyword.
Things don't always go so well, when I meet the Backtracking, I am stuck. for example, The subset problem. and my code is here: recursive call with loop
when i use user defined Stack to turn it to non-recursive form. I do not know how to deal with the loop (in the loop existing recursive call).
I googled found that there is many methods such as CPS. and I know there is an iterative template of subset problem. but i only want to use user defined Stack to solve.
Can someone provide some clues to turn this kind of recursive(recursive with loop) to non-recursive form(by using user defined Stack, not CPS etc..) ?
here is my code recursive to non-recusive(Inorder-Traversal), because of there is no loop with recursive call, so i can easily do it. also when recursive program with a return value, I can use a reference and pass it to the function as a param. from the code, I use the Stack to simulated the recursive call, and use "state" variable to the next call point(because java does not allow using GOTO).
The following is the information I have collected. It seems that all of them does not satisfy the question I mentioned(some use goto that java not allowed, some is very simple recursive means that no nested recursive call or recursive call with loop ).
1 Old Dominion University
2 codeproject
----------------------------------Split Line--------------------------------------
Thks u all. after when I post the question... It took me all night to figure it out. here is my solution: non-recursive subset problem solution, and the comment of the code is my idea.
To sum up. what i stuck before is how to deal with the foo-loop, actually, we can just simply ignore it. because we are using loop+stack, we can do a simple judgment on whether to meet the conditions.
On your stack, have you thought about pushing i (the iteration variable)?
By doing this, when you pop this value, you know at which iteration of the loop you were before you pushed on the stack and therefore, you can iterate to the next i and continue your algorithm.
Non-negative numbers only for simplicity. (Also no IntFunction.)
The power function, as defined here, is a very simple case.
int power(int x, int exponent) {
if (exponent == 0) {
return 1;
} else if (exponent % 2 == 0) {
int y = power(x, exponent /2);
return y * y;
} else {
return x * power(x, exponent - 1);
}
}
Now the stack is there to do in the reverse order to a partial result, what you did in recursion with the result.
int power(final int x, int exponent) {
Stack<Function<Integer, Integer>> opStack = new Stack<>();
final Function<Integer, Integer> square = n -> n * n;
final Function<Integer, Integer> multiply = n -> x * n;
while (exponent > 0) {
if (exponent % 2 == 0) {
exponent /= 2;
opStack.push(square);
} else {
--exponent;
opStack.push(multiply);
}
}
int result = 1;
while (!opStack.isEmpty()) {
result = opStack.pop().apply(result);
}
return result;
}
An alternative would be to "encode" the two branches of if-else (odd/even exponent) by a boolean:
int power(final int x, int exponent) {
BooleanStack stack = new BooleanStack<>();
while (exponent > 0) {
boolean even = exponent % 2 == 0;
stack.push(even);
if (even) {
exponent /= 2;
} else {
--exponent;
}
}
int result = 1;
while (!stack.isEmpty()) {
result *= stack.pop() ? result : x;
}
return result;
}
So one has to distinghuish:
what one does to prepare the recursive arguments
what one does with the partial results of the recursive calls
how one can merge/handle several recursive calls in the function
exploit nice things, like x being a final constant
Not difficult, puzzling maybe, so have fun.

How to correct my java recursive method so that I can use it to compute big value number?

It started from I want to compute 1+2+3+...+n, and
It is easy for me to figure out an recursive method to deal with repeat-plus-operation, and the code as follow:
public long toAccumulate(long num)
{
return num == 1 ? 1 : num + toAccumulate(num-1);
}
This method works just fine when use in a range of small number like 1 to 100, however, it fails to work when the parameter up to a big number like 1000000.
I wonder why?
And one leads to another, I write a repeat-times-operation method as follow:
public long toTimes(long num)
{
return num == 1 ? 1 : num * toTimes(num-1);
}
And here comes some interesting result. If I pass 100 as parameter, I will get 0. So I decrease my parameter's value, and I finally got some number when the parameter passing 60, but the result was a very weird negative number -8718968878589280256.
This got me thinking, but it didn't too much time for me to rethink something I have learnt from C, which is long long big data value type. And I assumed that negative number showed off is because the result data too big to fit in the current data type. What amazed me was I realize that there's a BigInteger class in Java, and I remembered this class can operate the big value data, so I changed the first code as follow:
public BigInteger toAccumulate(BigInteger num)
{
return num.equals(1) ? BigInteger.valueOf(1) : (num.add(toAccumulate(num.subtract(BigInteger.valueOf(1)))));
}
But it still didn't work... and this is driving me crazy...
A question I found in the stack overflow which similar to mine
According to the people who answered the question, I guess it may be the same reason that cause the bug in my code.
But since the BigInteger class didn't work, I think this must be the solution to this kind of accumulation problem.
What will you people do when you need to accumulate some number and prevent it go out of the maximum of data type? But is this really the data type problem?
return num.equals(1)
? BigInteger.valueOf(1)
: (num.add(toAccumulate(num.subtract(BigInteger.valueOf(1)))));
should probably be
return num.equals(BigInteger.valueOf(1))
? BigInteger.valueOf(1)
: (num.add(toAccumulate(num.subtract(BigInteger.valueOf(1)))));
...though frankly I'd write it as a method accepting an int and returning a BigInteger.
What if you try this:
public static BigInteger toAccumulate (BigInteger num)
{
if (num.equals(BigInteger.valueOf(1)))
{
return BigInteger.valueOf(1) ;
}
else
{
// 1+2+...+(n-1)+n = (n)(n+1)/2
BigInteger addOne = num.add(BigInteger.valueOf(1));
return num.multiply(addOne).divide(BigInteger.valueOf(2));
}
}
Here's how you can do the 1*2*3*....*(n-1)*n
public static BigInteger toTimes (BigInteger num)
{
// Should check for negative input here
BigInteger product = num;
// while num is greater than 1
while (num.compareTo(BigInteger.valueOf(1)) == 1)
{
BigInteger minusOne = num.subtract(BigInteger.valueOf(1));
product = product.multiply(minusOne);
num = minusOne; // num--;
}
return product;
}
Note: This is essentially the Factorial Function

Given a number, find which numbers below it divide it using recursion

I can't seem to figure this one out. I need to count how many numbers below a given number in which it is divisible.
Here is what I've tried:
public int testing(int x) {
if (x == 0) {
System.out.println("zero");
return x;
}
else if ((x % (x-1)) == 0) {
System.out.println("does this work?");
x--;
}
return testing(x-1);
}
That doesn't work and I don't know where to go from here. Anyone know what to do?
This is what is wrong:
public int testing(int x) {
If you want to make it recursive, you need to pass both the number to test and the number that you are currently checking. The first one will not change through the recursion, the second one will decrement. You cannot do what you express with only one parameter (unless you use a global variable).
This is not a task that should be solved with recursion.
If you MUST use recursion, the simplest way to do it is to have a second parameter, which is essentially an "I have checked until this number". Then you can increase/decrease this (depending on if you start at 0 or the initial number) and call the recursive on that.
Thing is, Java isn't a functional language, so doing all this is actually kind of dumb, so whoever gave you this exercise probably needs a bop on the head.
Your problem is that your expression x % (x - 1) is using the "current" value of x, which decrements on every call to the recursive function. Your condition will be false all the way down to 2 % (2 - 1).
Using a for loop is a much better way to handle this task (and look at the Sieve of Eratosthenes), but if you really have to use recursion (for homework), you'll need to pass in the original value being factored as well as the current value being tried.
You have a problem with your algorithm. Notice the recursion only ends when x == 0, meaning that your function will always return 0 (if it returns at all).
In addition, your algorithm doesn't seem to make any sense. You are basically trying to find all factors of a number, but there's only one parameter, x.
Try to make meaningful names for your variables and the logic will be easier to read/follow.
public int countFactors(int number, int factorToTest, int numFactors)
{
if (factorToTest == 0) // now you are done
return numFactors;
else
// check if factorToTest is a factor of number
// adjust the values appropriately and recurse
}
There is no need to use recursion here. Here's a non-recursive solution:
public int testing(int n) {
int count = 0;
for (int i = 1; i < n; i++)
if (n % i == 0)
count++;
return count;
}
BTW, you should probably call this something other than testing.
Using recursion:
private static int getFactorCount(int num) {
return getFactorCount(num, num - 1);
}
private static int getFactorCount(int num, int factor) {
return factor == 0 ? 0 : (num % factor == 0 ? 1 : 0)
+ getFactorCount(num, factor - 1);
}
public static void main(String[] args) {
System.out.println(getFactorCount(20)); // gives 5
System.out.println(getFactorCount(30)); // gives 7
}

proper way to store large numbers in a variable

I would like to play around with numbers and however elementary, Ive been writing algorithms for the fibonacci sequence and a brute force path for finding prime numbers!
Im not a programmer, just a math guy.
However, a problem I run into quiet often is that a long long, double and floats often run out of room.
If I wanted to continue to work in JAVA, in what way can I create my own data type so that I dont run out of room.
Conceptually, I thought to put 3 doubles together like so,
public class run {
static double a = 0;
static double b = 0;
//static double c = 0;
static void bignumber(boolean x) {
if (x == true && a < 999999999) {
++a;
} else if (x == true && a == 999999999) {
++b;
a = 0;
}
System.out.print(b + "." + a + " \n");
}
public static void main(String[] args) {
while(true) {
bignumber(true);
}
}
}
is there a better way to do this,
I would like to one day be able to say
mydataType X = 18476997032117414743068356202001644030185493386634
10171471785774910651696711161249859337684305435744
58561606154457179405222971773252466096064694607124
96237204420222697567566873784275623895087646784409
33285157496578843415088475528298186726451339863364
93190808467199043187438128336350279547028265329780
29349161558118810498449083195450098483937752272570
52578591944993870073695755688436933812779613089230
39256969525326162082367649031603655137144791393234
7169566988069
or any other number found on this site
I have also tried
package main;
import java.math.BigInteger;
public class run {
BigDecimal a = 184769970321174147430683562020019566988069;
public static void main(String[] args) {
}
}
But it still seems to be out of range
Use BigDecimal (instead of double), and BigInteger (instead of int, long) for that purpose, But you can only work with them by their methods. No operators, can be used.
Used like this:
BigInteger big = new BigInteger("4019832895734985478385764387592") // Strings...
big.add(new BigInteger("452872468924972568924762458767527");
Same with BigDecimal
BigDecimal is the class used in java where you need to represent very large or very small numbers, and maintain precision. The drawbacks are that it is not a primitive, so you can't use the normal math operators (+/-/*/etc), and that it can be a little processor/memory intensive.
You can store large numbers like this:
length
digits[]
and implement your math for them. This is not very complicated. As a hint, to make everything more simple you can store the digits in reverse order. This will make your math simpler to implement - you always add nr[k] with nr[k] and have room for transport for any length numbers, just remember to fill with 0 the shorter one.
In Knuth Seminumeric Algorithms book you can find a very nice implementation for all operations.

Categories

Resources