0

Consider the following code:

#include <iostream>
using namespace std;
int rec(float in){
   if(in < 0) return 0;
   else if(n == 0) return 1;
   else return(rec(in-.2));
}
int man(){
   int n;
   cin >> n;
   cout << rec (n);
   return 0;
}

I expect it to print 1 when the input is 1. But it prints 0. What went wrong here?

Ape-inago
  • 1,870
  • 1
  • 13
  • 27
  • 1
    Floats are not exact; see [this related question](http://stackoverflow.com/questions/588004/is-floating-point-math-broken?rq=1). – Kenney Nov 21 '15 at 13:15
  • 3
    There's a lot of implicit type conversion going on here. It's strange that a tail-recursing function like yours accepts a float and returns an int. – O. Jones Nov 21 '15 at 13:17
  • @OllieJones what's strange about returning an int? – Pascal Cuoq Nov 21 '15 at 21:35
  • @PascalCuoq its strange, but because the chaining happens before the return, every time the float is passed up it is deeper level, it is subtracted. but as it pulls back out from the recursion, it gets cast into an int - good catch. – Ape-inago Nov 23 '15 at 14:24
  • @Ape-inago There is no rule that a recursive function has to return the same type as its argument. Many useful recursive functions can be written that do not have this property. `qsort` takes 3 arguments and returns `void`, how is that for not returning the same type as one's argument? – Pascal Cuoq Nov 23 '15 at 15:31
  • @PascalCuoq doesn't have to be against the rules to be strange - mostly it raises questions about the point of the code. – Ape-inago Nov 23 '15 at 15:33
  • @Ape-inago A recursive function that returns a different type than its argument(s) only raises question if one does not understand recursion. The type of the function in the question indicates it returns an `int`. Indeed, the implementation of the function indicates it returns either `0`, `1` or `rec(…)`, all of which are of type `int`. There is no conversion (the thing that you incorrectly call “cast”) here. The only conversions are in `in < 0` and in `in == 0`, where the `int` constant `0` is converted to `float`. – Pascal Cuoq Nov 23 '15 at 15:37
  • @PascalCuoq Looking again, you are right the float 'in' never gets re-cast (coerced? converted? changed? adapted? molded? shaped? massaged?) to an int inside of the function - the int '0' gets turned into a float - I said it backwards. – Ape-inago Nov 23 '15 at 17:39

1 Answers1

1

In these lines

if(in < 0) return 0;
else if(in == 0) return 1;

Your code is running a comparison between an integer and a float. Specifically 'in < 0' and 'in == 0'. This is generally not going to give you the results you expect for various reasons (see article).

Now, you could cast the value 0 to a float, or change it to '0.0', but that wouldn't really solve your problem.

The real issue is that every time you subtract 0.2 away from the number, it creates a number that is almost but not quite 0.2 less than before. This happens because in c/c++, floating point numbers are represented/stored in their binary form using a standard format known as IEEE Standard for Floating-Point Arithmetic / IEEE 754. And per the article I linked earlier, it is probably not storing the intermediate results as 0.8 -> 0.6 -> 0.4 etc.

You can quickly check what is actually happening by echoing out the values within rec:

#include <limits>
// allows for use of numeric_limits<float>::digits10
// which tells us the precision of 
// the floating point number represented in decimal
// without having to know the specifics of the platform.

/*** [omitted code] ***/

int rec(float in){
   cout << setprecision(numeric_limits<float>::digits10) << in << ' ' << flush;
   /* flush will force the ostream to display to the screen
      instead of waiting for the buffer to fill up.
      useful if the recursive function never exits for some reason. */
   if(in < 0) return 0;
   else if(in == 0) return 1;
   else return(rec(in-.2));
}

And you should see that the value of 'in' ends up never actually equaling 0, so the bit of code returning 1 is never actually triggered.

The actual values will vary depending on your CPU architecture - I'd love to see what yours prints out.

Ape-inago
  • 1,870
  • 1
  • 13
  • 27
  • i did a little bit editing to my code like this: cout << in << " " << endl; it showed: 1 .8 .6 .4 .2 3.27e-8 -.2 how to solve this problem? – Redwanul Haque Sourave Nov 21 '15 at 16:50
  • @RedwanulSourav I updated my code to include some bits that make cout print out the entirety of the floating point without rounding it. – Ape-inago Nov 23 '15 at 14:21
  • @RedwanulSourav To actually solve your problem is a little trickier. Your code seems a bit odd, so I don't quite know what you are trying to do with your algorithm you've got in 'rec'. I recommend checking out this: http://stackoverflow.com/questions/17333/most-effective-way-for-float-and-double-comparison and reading the article I linked to if you want a better handle on floating point comparisons tho. – Ape-inago Nov 23 '15 at 14:30