Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Ive used the following function in one of my programs.
I have tried to make sure that my code is efficient however I cannot find any help online to tell me how to recognize where I could improve...
Is there any one that can help identify if there are any parts of this where I could improve (make faster) or run more efficiently
z, s and t are all integers
powerMod(z, s, t) {
int temp = 1;
while (s > 0) {
temp = temp * z;
s = s - 1;
}
temp = temp mod t;
return temp;
}
so the overall function of this is too calculate z to the power of s then mod it by n every time. very simple yet I cannot figure out how i can make this faster as it will be used by main program 100s or 1000s of times
so something like this?
using the exponentiation by square and ive used long just in case of overflow due to int * int...
int powMod(int z, int s, int t){
long result = 1; //int * int will never exceed the size of a long
long multiplicant = z;
while(s > 0){
if(s % 2 == 1) {
result *= multiplicant;
result %= t; // do modulo on each temporary result to keep accuracy
}
multiplicant *= multiplicant;
multiplicant %= t;
s /= 2;
}
return result;
}
First, note that your code will fail to do what you description asks to do for large inputs:
...so the overall function of this is too calculate z to the power of
s then mod it by n every time. ...
However, note that your code will break for large values due to integer overflow, since you will first try to calculate a huge number, which is likely to overflow - and only then you will invoke the mode operator.
The correct way to calculate the above is using the fact that:
(x*x*x*...*x) mod t == (...(((x mod t)*x) mod t)*...*x) mod t
The second calculation will yield the correct answer for much larger inputs, only assumption needed is x*t <= Integer.MAX_VALUE, which is a much simpler assumption.
As for your request to improve performance - the power operator is efficiently calculated using exponent by squaring. Make sure you utilize the above equation in this method as well to avoid mistakes for large inputs.
Another solution is to use java's BigInteger library, specifically the method BigInteger.modPow()
Instead of building your own operator, try using Math.pow() (and add the mod part).
Why not just use Math? Seems like the fastest way to me.
powerMod(double z, double s, double t)
{
double a = Math.pow(z, s);
return Math.floorMod(a, t);
}
If you are really concerned by performance you can use Guava.IntMath.pow() which does exponentiate in O(log(n)) time. Source code of this implementation is below:
public static int pow(int b, int k) {
checkNonNegative("exponent", k);
switch (b) {
case 0:
return (k == 0) ? 1 : 0;
case 1:
return 1;
case (-1):
return ((k & 1) == 0) ? 1 : -1;
case 2:
return (k < Integer.SIZE) ? (1 << k) : 0;
case (-2):
if (k < Integer.SIZE) {
return ((k & 1) == 0) ? (1 << k) : -(1 << k);
} else {
return 0;
}
default:
// continue below to handle the general case
}
for (int accum = 1;; k >>= 1) {
switch (k) {
case 0:
return accum;
case 1:
return b * accum;
default:
accum *= ((k & 1) == 0) ? 1 : b;
b *= b;
}
}
}
You should also note that in most practical cases regular Math.pow() will be enough for your solution. You should think about swapping algorithms if it really slows down your program.
Related
I am new to Java and am I trying to implement a recursive method for finding "n choose k".
However, I've run into a problem.
public class App {
public static void main(String[] args) throws Exception {
int n = 3;
int k = 2;
int result = combRecursion(n, k);
System.out.println(result);
}
private static int combRecursion(int n, int k) {
if (k == 0) {
return 1;
} else {
return (combRecursion(n - 1, k - 1) + combRecursion(n - 1, k));
}
}
Output:
many repetitions of this line:
at App.combRecursion(App.java:14)
It's possible to pick k items from the set of n items only if n is greater or equal to k.
You need to cut off fruitless branches of recursion spawn by the call combRecursion(n - 1, k) which doesn't reduce the number of item in the sample.
When you need to create a recursive method, it should always contain two parts:
Base case - that represents a set of edge-cases, trivial scenarios for which the result is known in advance. If the recursive method hits the base case (parameters passed to the method match one of the conditions of the base case), recursion terminates. In for this task, the base case will represent a situation when the source list was discovered completely and position is equal to its size (invalid index).
Recursive case - a part of a solution where recursive calls are made and where the main logic resides.
Your recursive case is correct: it spawns two recursive branches of execution (one will "pick" the current item, the second will "reject" it).
But in the base case, you've missed the scenario mentioned above, we need to address these situations:
n isn't large enough (k > n), so that is not possible to fetch k item. And the return value will be 0 (or instead of returning a value, you might throw an exception).
k == 0 result should be 1 (it's always possible to take 0 items, and there's only one way to do it - don't pick anything).
When k == n - there's only one way to construct a combination, as #akuzminykh has pointed out. And the return value will be 1
Note that because your goal is to get familiar with the recursion (I'm pretty sure that you're doing it as an exercise) there's no need to mimic the mathematical formula in your solution, use pure logic.
Here is how you can implement it:
private static int combRecursion(int n, int k) {
if (k > n) return 0; // base case - impossible to construct a combination
if (n == k || k == 0) return 1; // base case - a combination was found
// recursive case
return combRecursion(n - 1, k - 1) + combRecursion(n - 1, k);
}
main() - demo
public static void main(String[] args) {
System.out.println(combRecursion(3, 2));
System.out.println(combRecursion(5, 2));
}
Output
3 // pick 2 item from the set of 3 items
10 // pick 2 item from the set of 5 items
Your base case ought to include both n == k || k == 0 for "n choose k" to be implemented correctly. That way, both calls will eventually terminate (even though your current implementation is rather inefficient as it has exponential runtime). A better implementation would use the formula n!/k!/(n-k)! or the multiplicative formula to run in linear time:
int factorial(int n) {
int res = 1;
for (; n > 1; n--) {
res *= n;
}
return res
}
int choose(int n, int k) {
return factorial(n)/factorial(k)/factorial(n-k);
}
further optimizing this is left as an exercise to the reader (hint: a single for loop suffices).
I'm trying to make a simple calculator to practice recursion. This is my code and I'm getting a stack overflow error. I don't necessarily care about the code to make this work as I want to figure it out myself, but I'm not sure why I would get a stack over flow error for this.
Declared in my main:
int base=3,exponent=4;
My exponent method:
static int powerN(int base, int n)
{
if ( n == 0 ) return 0;
return base * powerN (1, n-(n-1));
}
You have at least three bugs I can see. x0 is one (not zero). You should handle the case of x1 (which is x). And, when you recurse you want to pass base and n - 1 (as is you are recursing on a power of 1 - which will always be one). Like,
static int powerN(int base, int n) {
if (n == 0) {
return 1;
} else if (n == 1) {
return base;
}
return base * powerN(base, n - 1);
}
I am trying to better understand recursion. I am writing a basic geometric series method which I know could be done easier with a loop but that is not the purpose. The method is producing the currect output for the values of 0 and 1 which is simply 1 and 1.5. But for 2 it is outputting 1.25 when it should be 1.75. Any pointers on a better way to approach this?
public static double geometricSum(int n) {
if(n == 0){
return 1;
}
n = n * 2;
return 1.0 / n + geometricSum((int) (1/Math.pow(2, n)));
}
This happens because you are casting a float into a int.
1/(2^2)=1/4=0.25 --> 0
As you are passing your float as an int you're not getting your thing working propperly.
So 0.25 + geometricSum(0)=1.25.
On the first one happens the same. you pass the 0.5, but turned into an int so you.re not getting your aproximation propperly done.
As an advice, ALWAYS put () on your math functions in order to make the program, and you yourself, understand in which order it computes the numbers.
The first problem is the cast to int, giving the wrong result, already described by reyeselda95.
There is a second problem hidden, which is that if you fix that you get this:
public static double geometricSum(double n) {
System.err.println("Calling with " + n);
if(n == 0){
return 1;
}
n = n * 2;
return 1.0 / n + geometricSum((1/Math.pow(2, n)));
}
Calling this with the provided value of 2, leads to a loop between calls with the following values, leading to a stack overflow.
...
Calling with 0.4999999999999999
Calling with 0.5000000000000001
Calling with 0.4999999999999999
Calling with 0.5000000000000001
...
This may be the function you are looking for, if I understand correctly:
public static double geometricSum(int count) {
if (count == 0) {
return 1;
}
return geometricSum(count-1) + Math.pow(2, -count);
}
Don't cast float to int;
When using float, are you sure your formula is correct? The recursion breaks if an argument is zero, but you will get StackOverflowError when passing the result of 1.0/Math.pow(2, n) to the function.
This is my python code:
def geometricSum(k):
if k == 0:
return 1
return 1/2**k + geometricSum(k-1)
k = int(input())
print(geometricSum(k))
This is all about the power of 2 i.e. 2 Pow n where n is an integer.
Here Recursion is used to get the sequence of values for n.
In my case I've to calculate the value for 1/(2 pow n).
I have written multiple attempts to this problem, but I think this is the closest I could get. This solution makes the method recurse infinitely, because I don't have a base case, and I can't figure it out. The counter++ line is unreachable, and I can't get this to work, and I am very tired. This would be very easy with a loop, but recursion is kind of a new concept to me, and I would be thankful if someone helped me solve this.
public static double pi(int a, double b){
int counter=0;
if (counter %2==0){
return a-(a/(pi(a,b+2)));
counter++;
} else {
return a+(a/(pi(a,b+2)));
counter++;
}
You could pass in another int, say limit, and add this code:
if (b > limit) {
return a;
}
Or you could pass in some tolerance value:
if (pi(a,b+2) < tolerance) {
return a;
}
Whenever you're working with recursion it's good to establish an exit strategy up front.
Here is an implementation that works. Do not use it:
public static double term(double acc, int n, int r) {
if (r-- > 0) {
double sgn = (n % 4 == 1) ? +1.0 : -1.0;
acc += sgn * 4.0 / n;
n += 2;
return term(acc, n, r);
} else {
return acc;
}
}
public static double pi() {
return term(0.0, 1, 1000);
}
The reason not to use it is that this particular infinite series is a particularly poor way of calculating π because it converges very slowly. In the example above event after 1000 iterations are performed it's still only correct to 3 decimal places because the final calculated term is 4 / 1000.
Going much beyond 1000 iterations results in a stack overflow error with little improvement in the accuracy even though the term function is (I think) potentially tail recursive.
I have had a long time trying to convert this function into a loop but I can't find the way to do it. I have started with a while(m != 0) and then the conditionals inside, but the third if is the one that won't let me do it.
public static int calculatePayment(int n, int m){
if(m == 0) return n + 1;
if(n == 0 && m > 0) return calculatePayment(1, m - 1);
if(n > 0 && m > 0) return calculatePayment(calculatePayment(n - 1, m), m - 1);
return 0;
}
Also, I don't know is I need to use a BigInteger, aretrograde and inverteds the program will run StackOverFlow Error and won't let me know if I need it.
Edits:
1st:
m cannot be less than zero in the input, that will never happen. Same situation with n, the code doesn't need to handle that.
So far I have this:
while(m > 0){
if(n == 0 && m > 0){n = 1; m--;}
if(n > 0 && m > 0){m--; n = IDONTKNOWWHAT;}//here n is the value of
//the payment if n = n - 1
//and m = m
//here is the big deal.
}
if(m == 0) return n + 1; //or print
Also the code cannot be reduced to a mathematical formula, I tried.
It looks like you're trying to find a non-recursive algorithm for computing the Ackermann's function. I wouldn't mind having my salary computed like that:) I guess its an attempt to disguise a homework?
Anyway, you can just simulate the stack and store intermediate values and then it's quite easy, see: How to rewrite Ackermann function in non-recursive style?
By the way, Ackermann's function grows extremely fast. You could use BigInteger but it would be mostly futile anyway. Exact values of the function are known only for a couple of the smallest arguments. Also, a lot of recursion is involved so you need to cache intermediate values to postpone the StackOverflow, google about memoization.