Here is my short implementation of Russian Peasant Multiplication. How can it be improved?
Restrictions : only works when a>0,b>0
for(p=0;p+=(a&1)*b,a!=1;a>>=1,b<<=1);
It can be improved by adding whitespace, proper indentation, and a proper function body:
int peasant_mult (int a, int b) {
for (p = 0;
p += (a & 1) * b, a != 1;
a /= 2, b *= 2);
return p;}
See? Now it's clear how the three parts of the for declaration are used. Remember, programs are written mainly for human eyes. Unreadable code is always bad code.
And now, for my personal amusement, a tail recursive version:
(defun peasant-mult (a b &optional (sum 0))
"returns the product of a and b,
achieved by peasant multiplication."
(if (= a 1)
(+ b sum)
(peasant-mult (floor (/ a 2))
(* b 2)
(+ sum (* b (logand a 1))))))
I think it's terrible
This is exactly the same code from the compiler's point of view, and (hopefully) a lot clearer
int sum = 0;
while(1)
{
sum += (a & 1) * b;
if(a == 1)
break;
a = a / 2;
b = b * 2;
}
And now I've written it out, I understand it.
There is an really easy way to improve this:
p = a * b;
It has even the advantage that a or b could be less than 0.
If you look how it really works, you will see, that it is just the normal manual multiplication performed binary. You computer does it internaly this way (1), so the easiest way to use the russian peasant method is to use the builtin multiplication.
(1) Maybe it has a more sophasticated algorithm, but in principle you can say, it works with this algorithm
There is still a multiplication in the loop. If you wanted to reduce the cost of the multiplications, you could use this instead:
for(p=0;p+=(-(a&1))&b,a!=1;a>>=1,b<<=1);
I don't find it particularly terrible, obfuscated or unreadable, as others put it, and I don't understand all those downvotes. This said, here is how I would "improve" it:
// Russian Peasant Multiplication ( p <- a*b, only works when a>0, b>0 )
// See http://en.wikipedia.org/wiki/Ancient_Egyptian_multiplication
for( p=0; p+=(a&1)*b, a!=1; a>>=1,b<<=1 );
This is for a code obfuscation contest? I think you can do better. Use misleading variable names instead of meaningless ones, for starters.
p is not initialised.
What happens if a is zero?
What happens if a is negative?
Update: I see that you have updated the question to address the above problems. While your code now appears to work as stated (except for the overflow problem), it's still less readable than it should be.
I think it's incomplete, and very hard to read. What specific sort of feedback were you looking for?
int RussianPeasant(int a, int b)
{
// sum = a * b
int sum = 0;
while (a != 0)
{
if ((a & 1) != 0)
sum += b;
b <<= 1;
a >>= 1;
}
return sum;
}
Answer with no multiplication or division:
function RPM(int a, int b){
int rtn;
for(rtn=0;rtn+=(a&1)*b,a!=1;a>>=1,b<<=1);
return rtn;
}
Related
This is my homework:
I haven't tried to write the part of Natural Logarithm because I can't solve the part of Exponential.
This is the the approximations of Exponential in C using Taylor Series expansion I wrote.
However, it returns inf. What did I do wrong?
#include <stdio.h>
// Returns approximate value of e^x
// using sum of first n terms of Taylor Series
float exponential(int n, float x)
{
float sum = 1.0f; // initialize sum of series
for (int a = n; a >= 0; ++a ) {
while (x * sum / a < 0.00001) {
break;
}
sum = 1 + x * sum / a;
return sum;
}
}
int main()
{
int n = 0;
float x = 1.0f;
printf("e^x = %.5f", exponential(n, x));
return 0;
}
With How do I ask and answer homework questions? in mind, I will give you a few things to have a careful look at.
From comment by Spektre:
from a quick look you are dividing by zero in while (x * sum / a < 0.00001) during first iteration of for loop as a=n and you called the function with n=0 ... also your code does not match the expansion for e^x at all
Have a look at the for loop:
for (int a = n; a >= 0; ++a )
What is the first value of a? The second? The third?
Keep in mind that the values are determined by ++a.
When will that loop end? It is determined by a >= 0. When is that false?
What is this loop doing?
while (x * sum / a < 0.00001) {
break;
}
I suspect that you programmed "English to C", as "do the outer loop while ...", which is practically from the assignment.
But the loop does something else. Apart from risking the division by 0 mentioned above, if the condition is true it will stay true and cause an endless loop, which then however is immediatly canceled in the first iteration.
The head of your function float exponential(int n, float x) expects n as a parameter. In main you init it with 0. I suspect you are unclear about where that value n is supposed to come from. In fact it is unknown. It is more a result of the calculation than an input.
You are supposed to add up until something happens.
You do not actually ever need the value of n. This means that your for loop is meaningless. The inner loop (though currently pointless) is much closer to your goal.
I will leave it at this for now. Try to use this input.
Feel free to edit the code in your question with improvements.
(Normally that is not appreciated, but in case of homework dialog questions I am fine with it.)
Your current implementation attempt is quite a bit off. Therefore I will describe how you should approach calculating such a series as given in your quesiton.
Let's look at your first formula:
You need to sum up terms e(n) = x^n / n!
To check with your series: 1 == x^0 / 0! - x == x^1 / 1! - ...
To calculate these terms, you need a simple rule how to get from e(n) to e(n+1). Looking at the formula above we see that you can use this rule:
e(n+1) = e(n) * x / (n+1)
Then you need to create a loop around that and sum up all the bits & pieces.
You are clearly not supposed to calculate x^n/n! from scratch in each iteration.
Your condition to stop the loop is when you reach the limit of 1e-5. The limit is for the new e(n+1), not for the sum.
For the other formulas you can use the same approach to find a rule how to calculate the single terms.
You might need to multiply the value by -1 in each step or do something like *x*n/(n+1) instead of *x/(n+1) etc.
Maybe you need to add some check if the formula is supposed to converge. Then maybe print some error message. This part is not clear in your question.
As this is homework, I only point into the direction and leave the implementation work to you.
If you have problems with implementation, I suggest to create a new question.
#include <stdio.h>
int main() {
float power;
printf("Enter the power of e\n");
scanf("%f", &power);
float ans = 1;
float temp = 1;
int i = 1;
while ((temp * power) / i >= 0.00001) {
temp = (temp * power) / i;
ans = ans + temp;
i++;
}
printf("%.5f", ans);
return 0;
}
I think I solved the problem
But the part about Natural Log is not solved, I will try.
I'm trying to solve a problem where given an integer n, and an array of integers a -- can n be represented as a linear combination of elements from a such that the coefficients are positive integers as well.
I saw C: check if an integer is linear combination of elements in an array and implemented it as such in C, but it doesn't work in all cases.
int gcd(int a, int b) {
if (a == 0) {
return b;
}
return gcd(b % a, a);
}
bool can_be_changed(const int a[], int len, int val) {
for (int i = 0; i < len - 1; i++) {
for (int j = i + 1; j < len; j++) {
if (val % gcd(a[i], a[j]) == 0) {
return true;
}
}
}
return false;
}
But, if a = {4,5,6} and val=7 the code will return true as gcd(4,5) = 1 and 7 % gcd(4,5) == 0 will evaluate to true thus returning true which it shouldn't.
Any help is appreciated, thanks!
TL;DR: easiest algorithm is here, most efficient algorithm is explained below.
When you restrict the coefficients to positive integers, this problem is NP-complete (as long as len is part of the input and not fixed). So a truly efficient solution isn't going to happen. (It's called the Unbounded Subset Sum Problem, if you want to google around; a proof of its hardness is here.)
The most efficient algorithm I've found is from this paper:
The ⊕t operation is a "capped sumset", also described in the paper: it basically operates like this (sketched in Python):
def capped_sumset(a, b, t): # a, b sets of naturals, t natural
a0 = a | {0}
b0 = b | {0}
return {
x+y
for x in a0
for y in b0
if x+y <= t
}
The hardest part about implementing this in C is going to be all the set operations; once you have a good implementation of sets of integers, the algorithm itself isn't too bad.
If you don't care about efficiency, of course, you can use the "classic dynamic program" mentioned in the base case of the algorithm; you can find a detailed explanation with examples in several programming languages here. But be prepared for an exponential running time!
This is my idea of solving 'nth term of fibonacci series with least processing power'-
int fibo(int n, int a, int b){
return (n>0) ? fibo(n-1, b, a+b) : a;
}
main(){
printf("5th term of fibo is %d", fibo(5 - 1, 0, 1));
}
To print all the terms, till nth term,
int fibo(int n, int a, int b){
printf("%d ", a);
return (n>0)? fibo(n-1, b, a+b): a;
}
I showed this code to my university professor and as per her, this is a wrong approach to solve Fibonacci problem as this does not abstract the method. I should have the function to be called as fibo(n) and not fibo(n, 0, 1). This wasn't a satisfactory answer to me, so I thought of asking experts on SOF.
It has its own advantage over traditional methods of solving Fibonacci problems. The technique where we employ two parallel recursions to get nth term of Fibonacci (fibo(n-1) + fibo(n-2)) might be slow to give 100th term of the series whereas my technique will be lot faster even in the worst scenario.
To abstract it, I can use default parameters but it isn't the case with C. Although I can use something like -
int fibo(int n){return fiboN(n - 1, 0, 1);}
int fiboN(int n, int a, int b){return (n>0)? fiboN(n-1, b, a+b) : a;}
But will it be enough to abstract the whole idea? How should I convince others that the approach isn't wrong (although bit vague)?
(I know, this isn't sort of question that I should I ask on SOF but I just wanted to get advice from experts here.)
With the understanding that the base case in your recursion should be a rather than 0, this seems to me to be an excellent (although not optimal) solution. The recursion in that function is tail-recursion, so a good compiler will be able to avoid stack growth making the function O(1) soace and O(n) time (ignoring the rapid growth in the size of the numbers).
Your professor is correct that the caller should not have to deal with the correct initialisation. So you should provide an external wrapper which avoids the need to fill in the values.
int fibo(int n, int a, int b) {
return n > 0 ? fibo(b, a + b) : a;
}
int fib(int n) { return fibo(n, 0, 1); }
However, it could also be useful to provide and document the more general interface, in case the caller actually wants to vary the initial values.
By the way, there is a faster computation technique, based on the recurrence
fib(a + b - 1) = f(a)f(b) + f(a - 1)f(b - 1)
Replacing b with b + 1 yields:
fib(a + b) = f(a)f(b + 1) + f(a - 1)f(b)
Together, those formulas let us compute:
fib(2n - 1) = fib(n + n - 1)
= fib(n)² + fib(n - 1)²
fib(2n) = fib(n + n)
= fib(n)fib(n + 1) + fib(n - 1)fib(n)
= fib(n)² + 2fib(n)fib(n - 1)
This allows the computation to be performed in O(log n) steps, with each step producing two consecutive values.
Your result will be 0, with your approaches. You just go in recursion, until n=0 and at that point return 0. But you have also to check when n==1 and you should return 1; Also you have values a and b and you do nothing with them.
i would suggest to look at the following recursive function, maybe it will help to fix yours:
int fibo(int n){
if(n < 2){
return n;
}
else
{
return (fibo(n-1) + fibo(n-2));
}
}
It's a classical problem in studying recursion.
EDIT1: According to #Ely suggest, bellow is an optimized recursion, with memorization technique. When one value from the list is calculated, it will not be recalculated again as in first example, but it will be stored in the array and taken from that array whenever is required:
const int MAX_FIB_NUMBER = 10;
int storeCalculatedValues[MAX_FIB_NUMBER] = {0};
int fibo(int n){
if(storeCalculatedValues[n] > 0)
{
return storeCalculatedValues[n];
}
if(n < 2){
storeCalculatedValues[n] = n;
}
else
{
storeCalculatedValues[n] = (fibo(n-1) + fibo(n-2));
}
return storeCalculatedValues[n];
}
Using recursion and with a goal of least processing power, an approach to solve fibonacci() is to have each call return 2 values. Maybe one via a return value and another via a int * parameter.
The usual idea with recursion is to have a a top level function perform a one-time preparation and check of parameters followed by a local helper function written in a lean fashion.
The below follows OP's idea of a int fibo(int n) and a helper one int fiboN(int n, additional parameters)
The recursion depth is O(n) and the memory usage is also O(n).
static int fib1h(int n, int *previous) {
if (n < 2) {
*previous = n-1;
return n;
}
int t;
int sum = fib1h(n-1, &t);
*previous = sum;
return sum + t;
}
int fibo1(int n) {
assert(n >= 0); // Handle negatives in some fashion
int t;
return fib1h(n, &t);
}
#include <stdio.h>
int fibo(int n);//declaring the function.
int main()
{
int m;
printf("Enter the number of terms you wanna:\n");
scanf("%i", &m);
fibo(m);
for(int i=0;i<m;i++){
printf("%i,",fibo(i)); /*calling the function with the help of loop to get all terms */
}
return 0;
}
int fibo(int n)
{
if(n==0){
return 0;
}
if(n==1){
return 1;
}
if (n > 1)
{
int nextTerm;
nextTerm = fibo(n - 2) + fibo(n - 1); /*recursive case,function calling itself.*/
return nextTerm;
}
}
solving 'nth term of fibonacci series with least processing power'
I probably do not need to explain to you the recurrence relation of a Fibonacci number. Though your professor have given you a good hint.
Abstract away details. She is right. If you want the nth Fibonacci number it suffices to merely tell the program just that: Fibonacci(n)
Since you aim for least processing power your professor's hint is also suitable for a technique called memoization, which basically means if you calculated the nth Fibonacci number once, just reuse the result; no need to redo a calculation. In the article you find an example for the factorial number.
For this you may want to consider a data structure in which you store the nth Fibonacci number; if that memory has already a Fibonacci number just retrieve it, otherwise store the calculated Fibonacci number in it.
By the way, didactically not helpful, but interesting: There exists also a closed form expression for the nth Fibonacci number.
This wasn't a satisfactory answer to me, so I thought of asking
experts on SOF.
"Uh, you do not consider your professor an expert?" was my first thought.
As a side note, you can do the fibonacci problem pretty much without recursion, making it the fastest I know approach. The code is in java though:
public int fibFor() {
int sum = 0;
int left = 0;
int right = 1;
for (int i = 2; i <= n; i++) {
sum = left + right;
left = right;
right = sum;
}
return sum;
}
Although #rici 's answer is mostly satisfactory but I just wanted to share what I learnt solving this problem. So here's my understanding on finding fibonacci using recursion-
The traditional implementation fibo(n) { return (n < 2) n : fibo(n-1) + fibo(n-2);} is a lot inefficient in terms of time and space requirements both. This unnecessarily builds stack. It requires O(n) Stack space and O(rn) time, where r = (√5 + 1)/2.
With memoization technique as suggested in #Simion 's answer, we just create a permanent stack instead of dynamic stack created by compiler at run time. So memory requirement remains same but time complexity reduces in amortized way. But is not helpful if we require to use it only the once.
The Approach I suggested in my question requires O(1) space and O(n) time. Time requirement can also be reduced here using same memoization technique in amortized way.
From #rici 's post, fib(2n) = fib(n)² + 2fib(n)fib(n - 1), as he suggests the time complexity reduces to O(log n) and I suppose, the stack growth is still O(n).
So my conclusion is, if I did proper research, time complexity and space requirement both cannot be reduced simultaneously using recursion computation. To achieve both, the alternatives could be using iteration, Matrix exponentiation or fast doubling.
I am trying to make from f_rec (recursive function) to f_iter (iterative function) but I can't.
(My logic was to create a loop to calculate the results of f_rec(n-1).
int f_rec(int n)
{
if(n>=3)
return f_rec(n-1)+2*f_rec(n-2)+f_rec(n-3);
else
return 1;
}
int f_iter(int n)
{
}
I also think that my time complexity for the f_rec is 3^n , please correct me if I'm wrong.
Thank you
There are two options:
1) Use the discrete math lessons and derive the formula. The complexity (well if #Sasha mentioned it) will be O(1) for both memory and algorithm. No loops, no recursion, just the formula.
At first you need to find the characteristic polynomial and calculate its roots. Let's asssume that our roots are r1, r2, r3, r4. Then the n'th element is F(n) = A * r1^n + B * r2^n + C * r3^n + D * r4^n, where A, B, C, D are some unknown coefficients. You can find these coefficients using your initial conditions (F(n) = 1 for n <= 3).
I can explain it on russian if you need.
2) Use additional variables to store intermediate values. Just like #6052 have answered (he has answered really fast :) ).
You can always calculate the newest value from the last three. Just start calculating from the beginning and always save the last three:
int f_iter (int n) {
int last3[3] = {1,1,1}; // The three initial values. Use std::array if C++
for (int i = 3; i <= n; ++i) {
int new_value = last3[0] + 2 * last3[1] + last3[2];
last3[0] = last3[1];
last3[1] = last3[2];
last3[2] = new_value;
}
return last3[2];
}
This solution need O(1) memory and O(n) runtime. There might exist a formula that calculates this in O(1) (there most likely is), but I guess for the sake of demonstrating the iteration technique, this is the way to go.
Your solution has exponential runtime: Every additional level spawns three evaluations, so you end up with O(3^n) operations and stack-memory.
The following is the idea
int first=1,second=1,third=1; /* if n<=3 then the respective is the answer */
for(i=4;i<=n;i++)
{
int next=first+2*second+third;
first=second;
second=third;
third=next;
}
cout<<"The answer is "<<next<<endl;
Memory is O(1) and time is O(n).
EDIT
Your recursive function is indeed exponential in time , to keep it linear you can make use
of an array F[n], and use memoization. First initialize F[] as -1.
int f_rec(int n)
{
if(n>=3)
{
if(F[n]!=-1)return F[n];
F[n]=f_rec(n-1)+2*f_rec(n-2)+f_rec(n-3);
return F[n];
}
else
return 1;
}
Just keep three variables and roll them over
start with a, b and c all equal to 1
at each step new_a is a + 2*b + c
roll over: new_c is b, new_b is a
repeat the required number of steps
A bit of an overkill, but this can be further optimized by letting the what the variables represent change in an unfolded loop, combined with (link) Duff's device to enter the loop:
int f_iter(int n){
int a=1, b=1, c=1;
if(n < 3)
return(1);
switch(n%3){
for( ; n > 2; n -= 3){
case 2:
b = c + 2*a + b;
case 1:
a = b + 2*c + a;
case 0:
c = a + 2*b + c;
}
}
return c;
}
I have a sequence.
a1 = 1 - cos(x);
ai = a1 + (-1)^(i-1) * x^(2*i-2) / (2*i-2)!
I need to write this with and without recursion. But it has a different results.
Here is my code: http://codepaste.net/q213q6
I'm going to operate under the assumption that this is homework, if I'm wrong I'll come back and edit this post or repost.
Firstly, you should try to write your factorial function in a tail recursive manner. Though it probably won't make much difference in C, it's good practice.
int helper( int x, int acc ) {
if( x == 0 ) {
return acc;
}
else {
return helper( x - 1, acc * x );
}
}
int factorial( x ) {
helper( x, 1 );
}
Next, you don't generally want to put a loop inside of your recursive functions, that somewhat defeats the point. Think of a recursive call as one iteration with a test and either return or recall.
Since you are performing floating point arithmetic. Different ways of implementation can produce different results.
In your case i can think of one place where losses are incurred
currC = pow(x, 2*i-2);
is not equal to
47: currC = currC * x * x;
For more information,
http://en.wikipedia.org/wiki/Floating_point#Multiplication