What is wrong with this recursive function? - c++

I have to write a recursive function (not using vector or string) to reverse a number and return it. For example if I enter 35, it should return 53. My code is (which is not working):
int reverse( int number )
{
if( number < 10 )
return number;
number = fmod(number,10);
return reverse( number );
}
If I enter 35 for example, this code gives me only 5... what happens to 3??

You cannot expect that a recursive function taking one single int and returning an int and making last digit first could successfully reverse a number. Let's imagine f does it, and see what happens for resp 1234 and 4123.
if you turn right, f(1234) should return f(4123) which is a non sense because we know that they will have different values. And if you turn lest f(4123) should return f(1234) exhibiting same problem.
That means that the recursive function should have at least 2 parameters, and the simpler is number_to_convert, number_converted_so_far, because now you have a correct stop point when the number to convert has no more digits.
In your code, the problem is that after first recursion, your number has only one single digit (the last one) so all other digits are irremidiably lost.

Are you allowed to pull in math library functions like log10?
#include <math.h>
int reverse(int number) {
if (number == 0) {
return number;
}
return (number % 10) * pow(10, floor(log10(number))) + reverse(number / 10);
}

Here is the correct function.
int fun(int a)
{
if(a<10)
return a;
int no=0,b=a;
while(b)
{
no++;
b/=10;
}
int l=a%10;
return l*pow(10,no-1)+fun(a/10);
}

Related

I don't understand why I need to put two lines in a specific order for it to work (recursion)

I just started to learn about recursion.
This program is supposed to calculate n! and store the result into an output parameter.
void factorial(int n, int &f)
{
if (n == 0)
{
f = 1;
}
else
{
factorial(n - 1, f);
f *= n;
}
}
int main()
{
int f;
factorial(5, f);
cout << f;
}
This way it works perfectly. In my first attempt, the else condition looked like this
else
{
f *= n;
factorial(n - 1, f);
}
and the program didn't output anything but 1.
I really can't understand why it works in the first way but in the second it doesn't. Can you explain to me?
In your code, factorial(0, f) will set f = 1. If you modify f before the call to factorial, it will be overwritten.
Note that this problem is not possible if you return int instead of taking int & as an argument.
For anyone wondering:
Using #ForceBru's suggestion I ran it on a piece of paper and I got it. If I do it in the second way, the last thing called will be factorial(0) which will return 1, even if I already calculated to be n!.
f is getting over written to 1 in your last call f(0). If you switch the statements then f gets initialized to 1 in the last call f(0) followed by It's modification before return of each function call

Using rand() to get a number but that number can't be the number that was last generated

I want to use std::rand() to generate a number between 0 and amountOfNumbers, but the generated number can't be the same number that was last generated.
I wrote this function:
void reroll() {
int newRand;
while (true) {
newRand = std::rand() % (amountOfNumbers);
if (newRand == lastNumber) {
continue;
}
lastNumber = newRand;
break;
}
// do something with newRand
// ...
}
amountOfNumbers is just an int (> 1) that defines the upper bound (e.g. 5 so the possible number range is 0 to 4). lastNumber which is initially -1 stores the last generated number.
I was wondering if there's a better way to write this.
The function seems to be working so far, but I'm not sure if my code is flawless... it looks kind of bad. That while (true) makes me feel a bit uneasy.
The code works but I'd structure it like this
int reroll(int n, int last) {
while(true) {
int v = std::rand() % n;
if(v!=last)
return v;
}
}
void reroll() {
...
int v = reroll(n, last);
...
}
Also you can avoid the need for the while loop altogether by generating values in a smaller range (1 less) and adjusting around last.
int reroll(int n, int last) {
if(last==-1)
return std::rand() % n;
int v = std::rand() % (n-1);
if (v<last) return v
return v+1;
}
I have a few suggestions.
Since you never declare lastNumber and amountOfNumbers, I am going to assume they are global. It would be better to pass these as variables to the function instead. Also, you should return the new number from the function instead of setting it as void.
The following code below will calculate a new roll. Instead of rerolling until there is a new roll, we will just take the random of the set of numbers, but one less. If the number is greater than or equal, we will add the one back in, thus avoiding the lastNumber. The function then returns the newRand. Doing it this way will avoid the (albeit low) risk of an infinite loop, and it will always run in constant time.
int reroll(int lastNumber, int amountOfNumbers)
{
int newRand;
newRand = std::rand() % (amountOfNumbers - 1);
if (newRand >= lastNumber) {
newRand++;
}
return newRand;
}
The while true loop is definitely not good practise, I'd suggest doing something like this. But you should make it in the same structure as Michael's answer above like this:
void reroll(int lastNumber, int amountOfNumbers) {
int newRand = std::rand() % (amountOfNumbers);
while (newRand == lastNumber) {
newRand = std::rand() % (amountOfNumbers);
}
lastNumber = newRand;
return newRand;
}
Depending on your value for amountOfNumbers, the modulus operation you've used might not guarantee an even distribution (which is a small part of your problem).
For a start, if amountOfNumbers is greater than RAND_MAX there will be numbers you'll never see using this.
Next, consider if you're using this to generate values between 0 and 6 ([0,1,2,3,4,5]) for a dice, and RAND_MAX is 7. You'll see the values 0 and 1 twice as often as the rest! In reality, RAND_MAX must be at least 32767 (whatever that means, which according to the standard isn't really much)... but that isn't evenly divisible by 6, either, so of course there will be some values that have a slight bias.
You can use modulus to reduce that range, but you'll probably want to discard the bias in the second problem. Unfortunately, due to the common implementation of rand, extending the range beyond max will introduce further bias.
unsigned int rand_range(unsigned int max) {
double v = max > RAND_MAX ? max : RAND_MAX;
v /= RAND_MAX;
int n;
do {
n = rand();
} while (RAND_MAX - n <= RAND_MAX % (unsigned int)(max / v));
return (unsigned int)(v * n) % max;
}
This still doesn't guarantee that there won't be any repeating values, but at least any bias causing repeating values will have been reduced significantly. We can use a similar approach to the (currently) accepted answer to remove any repeated values, with minimal bias, now:
unsigned int non_repetitive_rand_range(unsigned int max) {
if (max <= 1) {
return 0; // Can't avoid repetitive values here!
}
static unsigned int previous;
unsigned int current;
do {
current = rand_range(max);
} while (current != previous);
previous = current;
return current;
}
On a technical note, this doesn't necessarily guarantee a problem to the solution either. This quote from the standard explains why:
There are no guarantees as to the quality of the random sequence produced and some implementations are known to produce sequences with distressingly non-random low-order bits. Applications with particular requirements should use a generator that is known to be sufficient for their needs.
As a result, it is possible that some silly, obscure implementation might implement rand like so:
int rand(void) {
return 0;
}
For such an implementation, there's no avoiding it: This implementation of rand would cause the code in this answer (and all the other current answers) to go into an infinite loop. Your only hope would be to re-implement rand and srand. Here's an example implementation given within the standard, should you ever have to do that:
static unsigned long int next = 1;
int rand(void) // RAND_MAX assumed to be 32767
{
next = next * 1103515245 + 12345;
return (unsigned int)(next/65536) % 32768;
}
void srand(unsigned int seed)
{
next = seed;
}
You'll probably want to rename them to my_rand and my_srand respectively, and use #define rand my_rand and #define srand my_srand or use a find/replace operation.

What is wrong with the following code? It converts double to string without using sprintf or ostream

I wrote the following code for converting double to string.I was not supposed to use
sprintf or ostream . The output is quite erratic.
The list of input with corresponding output :
2.0 2.0
2.5 2.5
-2.0 -2.0
2.987 2.9879947598364142621957397469375
-2.987 -2.9879947598364142621957397469375
Where did these extra digits come from and how to overcome this?My code can be found below.
#include <iostream>
#include <math.h>
using namespace std;
string reverse(string input);
string myDtoA(double num);
string itoa(int num);
int main()
{
double inp=-2.987;
cout<<myDtoA(inp)<<endl;
}
string myDtoA(double num)
{
if(num>0)
{
int inPart;
double intPart,fractPart;
fractPart = modf(num,&intPart);
inPart=(int)intPart;
string ret;
ret = itoa(inPart);
if(fractPart!=0)
{
ret.append(".");
double ceilOfFraction = ceil(fractPart);
while(ceilOfFraction !=0)
{
double inP,fP;
fractPart*=10;
fP=modf(fractPart,&inP);
int a =(int)inP;
ret.append(itoa(a));
fractPart=fP;
ceilOfFraction = ceil(fractPart);
}
}
else
{ret.append(".0");}
return ret;
}
else if(num==0)
{
return "0";
}
else if(num<0)
{
string ret = "-";
ret.append(myDtoA(-num));
return ret;
}
}
string itoa(int num)
{
char* str = new char[120];
int i=0;
// Process individual digits
while (num != 0)
{
int rem = num % 10;
str[i++] = (rem > 9)? (rem-10) + 'a' : rem + '0';
num = num/10;
}
string ret(str);
return reverse(ret);
}
/* A utility function to reverse a string */
string reverse(string input)
{
return std::string(input.rbegin(), input.rend());
}
Rounding floating point output is hard.
Here's the most recent paper I found on the subject:
http://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf
In the footnotes, you'll find a reference to:
[Steele Jr. and White(2004)] G. L. Steele Jr. and J. L. White. How to
print floating-point numbers accurately (retrospective). In 20 Years of
the ACM SIGPLAN Conference on Programming Language Design and
Implementation 1979-1999, A Selection, pages 372–374. ACM, 2004. ISBN
1-58113-623-4. doi: 10.1145/989393.989431.
which is a wonderful exposition. No one is going to be able to pick through your program and tell you what to do to it.
The problem is in your implementation of itoa. What happens if the input to itoa is 0?
Your output of -2.9879947598364142621957397469375 for an input of -2.987 should be -2.9870000000000000994759830064140260219573974609375. Notice that the zeros in my result are missing from yours. Those missing zeros are because of that bug in itoa.
Once you get to the point of dealing with single decimal digits, your itoa is complete overkill. It would be better to use an array that maps the integers 0 to 9 to the characters '0' to '9'. (Or you could just use the fact that '0' to '9' are almost certainly contiguous characters on your computer. That hasn't alway been the case, but I can pretty much guarantee that you aren't working with such a beast.)
Even better would be to recognize that the substring starting with 99475983… is completely extraneous. It would be better to print this as -2.9870000000000001, and even better to print it as -2.987.

Not fulfilling If condition but the function still return something

Below is the code :
The Code :
#include <iostream>
using namespace std;
int sum(int ); //To sum up the user input up to 1 , for e.g 4 = 4 + 3 + 2 + 1 = 10
int main(void)
{
int num;
int total;
cin >> num;
total = sum(num);
cout << total;
return 0;
}
int sum(int num)
{
if(num > 0) // How if num is -1 or -10??
return num + sum(num - 1);
}
The Question :
1.) I try to execute the above code and input value that violate the if condition for e.g -1 or -100 . But still when I cout the total variable I get back the value I've given to the variable num .
2.) My question is , is this a standard behavior ? Because I can run this code without getting any warning or error saying there's no return statement stated I don't have an extra return statement in case the num is violating the condition . So is this returning- the-original-value-if-the-condition-is-not-true something normal or it depends on the compiler being used ?
THank you .
A function that promises to return a value and does not induces Undefined Behavior (in C, only if the value is used).
Here your function has two executions paths:
int sum(int num) {
if (sum > 0)
return num + sum(num - 1); // code path 1
// code path 2
}
And in the second code path, it does not return anything.
Undefined behavior means anything can happen. The popular image is that daemons could start flying out of your nose. In practice, you are more likely to get a more or less random value depending on the implementation. Looks like in your case, for your compiler, this program and that set of optimizations (and maybe because the stars aligned, too) you get num. Lucky you.
By the way, my compiler gives a warning:
source.cpp: In function 'int sum(int)':
source.cpp:22:1: warning: control reaches end of non-void function [-Wreturn-type]

Unhandled exception in C++ program

I'm trying to answer this question from my C++ book that says: There are n people in a room, where n is an integer greater than or equal to 2. Each person shakes hands once with every other person. What is the total number of handshakes in the room? Write a recursive function to solve this problem.
I've written a program, but nothing is being outputted from the function. I'm pretty sure my stuff inside the handshake function is correct, but nothing is being outputted by the function inside the main function. It keeps giving me an error:
Unhandled exception at 0x00c01639 in Problem2.exe: 0xC00000FD: Stack overflow.
Thank you for your help in advance!
#include <iostream>
#include <conio.h>
using namespace std;
int handshake(int n);
int main()
{
int i, n;
cout<<"How many people are in the room? ";
cin>>i;
for (n = 1; n = i; n++)
{
handshake(n);
}
cout<<"There are "<<handshake(n)<<" in the room"<<endl;
getche();
return 0;
}
int handshake(int n)
{
if (n == 1)
{
return 0;
}
else if (n == 2)
{
return 1;
}
else
{
return (handshake(n) + (n - 1));
}
}
Your problem is here:
return (handshake(n) + (n - 1));
Notice you're returning handshake(n) on a call of handshake(n), throwing you into infinite recursion land (and causing the call stack to overflow, hence your error).
This sounds like homework so I won't give any specific solution. I will make the following remarks:
Recursive functions need to have a base case (which you have) and a recursive step (which you need to fix). In particular, if f(x) is a recursive function, its result should depend on f(x-e), where e is strictly greater than 0.
You only need to call a recursive function once in your main code; it will take care of calling itself when needed.
The problem is because of stackoverflow which happens because the call to handshake(n) is making a recursive call to handshake(n) again and this infinite recursive calls causes the stack to explode.
Recursive calls should be called with arguments that are closer to the values that lead to base conditions, 0 and 1 in your case.
In your case the correct recursive call is:
return (handshake(n-1) + (n - 1));
As the recursive formula for number of hand shakes in a party is:
H(n) = H(n-1) + n-1
with the base condition of H(1) = 0 and H(2) = 1 where n is the number of people in the party and H(n) is the number of handshakes when every person in the party shakes hand with every other person in the party.
Also the condition in your for loop:
for (n = 1; n = i; n++)
will assign i to n. But what you want is to compare the value as:
for (n = 1; n <= i; n++)