#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    109
    Rep Power
    2

    Function turns my ints into garbage ??


    I have an exercise: "The country A has 50M inhabitants, and its population grows 3% per year. The country B, 70M and grows 2% per year. Tell in how many years A will surpass B."

    I wrote a recursive function that recieves 50.0 and 70.0 as floats, multiplies untill A>B, and returns the number of years.

    Inside the function, num_years prints correctly. When i try to use the return value i get a very large int (why??)

    Code:
    #include<stdio.h>
    
    int pop_count(float pop1, float pop2)
    {   
        static int num_years=0;
        
        if(pop1 > pop2)
            return num_years;
             
        ++num_years;
        pop_count((pop1)*=(1.03), (pop2)*=(1.02));
    }
    
    int main(void)
    {
        int ret=pop_count(50.0, 70.0);
        
    getch();
    return 0;      
    }
    Also when i test-print pop1 and pop2 it shows that pop1=0 for the first 3 rounds (!!) and afterwards both pop2 and pop1 receive very large values.

    I just can't see the mistake- can anybody see it ?? :confused:
    Last edited by C learner; August 30th, 2013 at 08:07 PM.
  2. #2
  3. Did you steal it?
    Devshed Supreme Being (6500+ posts)

    Join Date
    Mar 2007
    Location
    Washington, USA
    Posts
    13,988
    Rep Power
    9397
    The very last call in the stack will return num_years, but what about the calls happening before it? What will they return?

    And any reason why a static variable and not a loop? You could even jump right to the solution with a bit of math instead.

    [edit] With some printf()s I get output
    Code:
    50.000, 70.000
    51.500, 71.400
    53.045, 72.828
    54.636, 74.285
    56.275, 75.770
    57.964, 77.286
    59.703, 78.831
    61.494, 80.408
    63.339, 82.016
    65.239, 83.656
    67.196, 85.330
    69.212, 87.036
    71.288, 88.777
    73.427, 90.552
    75.629, 92.364
    77.898, 94.211
    80.235, 96.095
    82.642, 98.017
    85.122, 99.977
    87.675, 101.977
    90.306, 104.016
    93.015, 106.097
    95.805, 108.219
    98.679, 110.383
    101.640, 112.591
    104.689, 114.842
    107.830, 117.139
    111.064, 119.482
    114.396, 121.872
    117.828, 124.309
    121.363, 126.795
    125.004, 129.331
    128.754, 131.918
    132.617, 134.556
    136.595, 137.247
    140.693, 139.992
    Stopped after 35 iterations
    Code:
    $ gcc -v
    Using built-in specs.
    COLLECT_GCC=gcc
    COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.6/lto-wrapper
    Target: x86_64-linux-gnu
    Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.3-1ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
    Thread model: posix
    gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
    $
    Last edited by requinix; August 30th, 2013 at 08:27 PM.
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    109
    Rep Power
    2
    >>No, the exercise was to do it using C not math :P

    Oops, accidentally wrote %d instead of %f >_<

    Still, why does my compiler make ret a large int, whereas an online compiler got it all right ??
    Last edited by C learner; August 30th, 2013 at 08:56 PM.
  6. #4
  7. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,379
    Rep Power
    1871
    > Still, why does my compiler make ret a large int, whereas an online compiler got it all right ??

    Can you read?

    > requinix The very last call in the stack will return num_years, but what about the calls happening before it? What will they return?

    Also, getting two different results from two different compilers is a sign your code is broken in some way. In the large domain of undefined behaviour, all sorts of things can happen (including producing the right answer despite your best efforts to make a mess of it).

    Turn up the warning level on your compiler.
    Code:
    $ gcc -Wall baz.c
    baz.c: In function ‘main’:
    baz.c:16:9: warning: unused variable ‘ret’ [-Wunused-variable]
    baz.c: In function ‘pop_count’:
    baz.c:12:1: warning: control reaches end of non-void function [-Wreturn-type]

    Comments on this post

    • dwise1_aol agrees : "If you lie to the compiler, it will get its revenge." [Henry Spencer]
    Last edited by salem; August 30th, 2013 at 11:20 PM.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    109
    Rep Power
    2
    Ok, i just compiled my code in 5 (!) different online compilers and they all print the output the way it should work.

    >> What do the other calls return: Why would the other calls return ANYTHING if pop1 > pop2 is false all the way untill the last call ?
    Last edited by C learner; August 31st, 2013 at 05:45 AM.
  10. #6
  11. Did you steal it?
    Devshed Supreme Being (6500+ posts)

    Join Date
    Mar 2007
    Location
    Washington, USA
    Posts
    13,988
    Rep Power
    9397
    Originally Posted by C learner
    Ok, i just compiled my code in 5 (!) different online compilers and they all print the output the way it should work.
    That's great but your code is still flawed.

    Originally Posted by C learner
    >> What do the other calls return: As soon as the recursion reaches its final depth, it starts going backwards, each time checking pop1>pop2 and returning the SAME num_years to the level above it= 35. That number doesn't change anymore, right ?
    Your description is incorrect: the last call to pop_count will return, yes, but all the calls leading up to it don't. They only call pop_count without trying to return what it returned. Your code should have
    Code:
    return pop_count(pop1 * 1.03, pop2 * 1.02);
    (which also does away with the useless assignments).

    Originally Posted by C learner
    Is there something wrong with my compiler ?
    No, you're merely getting the right results from an incorrect input: just because it works in a few cases does not mean you're doing what you should do. -Wall, like salem demonstrated, will show you many potential problems with your code, and in this case it shows (1) the ret variable isn't used and (2) pop_count wasn't always returning. It just happens that the undefined behavior from not returning a value gave you the same result you were expecting.
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    109
    Rep Power
    2
    Does it mean that the function will NOT pass the num_years backwards (to the previous calls) since the permission to do it is by having the return command for the name of the function ?

    So basically num_years is passed just 1 level back, while it should be passed 35 levels back ?

    Am i correct ?

    -Sorry for my heavy editting.
    Last edited by C learner; August 31st, 2013 at 06:01 AM.
  14. #8
  15. Did you steal it?
    Devshed Supreme Being (6500+ posts)

    Join Date
    Mar 2007
    Location
    Washington, USA
    Posts
    13,988
    Rep Power
    9397
    Originally Posted by C learner
    Does it mean that the function will NOT pass the num_years backwards (to the previous calls) since the permission to do it is by having the return command for the name of the function ?

    So basically num_years is passed just 1 level back, while it should be passed 35 levels back ?

    Am i correct ?
    That's exactly it. There is no such "permission" thing: if you want the function to return the result of calling itself recursively then you have to write it as such in the code.
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    109
    Rep Power
    2
    That's exactly what i missed, thank you very much :)

    Now i fully understand recursion :cheers:

IMN logo majestic logo threadwatch logo seochat tools logo