Chapter 15 // Exercise 1
Here is another way of defining a factorial function:
int fac(int n) { return n > 1 ? n *fac(n - 1) : 1; } // factorial n!
It will do fac(4) by first deciding that since 4 > 1 it must be 4 * fac(3), and that's obviously 4 * 3 * fac(2), which again is 4 * 3 *2 * fac(1), which is 4 * 3 * 2 * 1. Try to see that it works. A function that calls itself is said to be recursive. The alternative implementation in section 15.5 is called iterative bcause it iterates through the values (using while). Verify that the recursive fac() works and gives the same results as the iterative fac() by calculating the factorial of 0, 1, 2, 3, 4, up until and including 20. Which implementation of fac() do you prefer, and why?
Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2015/Exercise%201int fac(int n) { return n > 1 ? n *fac(n - 1) : 1; } // factorial n!
It will do fac(4) by first deciding that since 4 > 1 it must be 4 * fac(3), and that's obviously 4 * 3 * fac(2), which again is 4 * 3 *2 * fac(1), which is 4 * 3 * 2 * 1. Try to see that it works. A function that calls itself is said to be recursive. The alternative implementation in section 15.5 is called iterative bcause it iterates through the values (using while). Verify that the recursive fac() works and gives the same results as the iterative fac() by calculating the factorial of 0, 1, 2, 3, 4, up until and including 20. Which implementation of fac() do you prefer, and why?
When using int, at 13 this will begin to overflow and return the wrong numbers.
I also did a quick benchmark test between the two functions and there isn't really any difference. I'd say half the time, the recursive function was faster by 0.002 nanoseconds. Sometimes iterative was a bit slower or recursive was slower. They seem to be pretty balanced speed-wise.
I looked at the disassembly and realised why they perform the same; the compiler produces the exact same assembly for both functions. I've kept this code in so you can run it yourself a few times.
So it comes down to preference. I prefer the recursive as it's less code and at a glance; easier to reason about what's happening. A lot of people don't like the ternary operator though so I can understand why the iterative version would be chosen instead.
I also did a quick benchmark test between the two functions and there isn't really any difference. I'd say half the time, the recursive function was faster by 0.002 nanoseconds. Sometimes iterative was a bit slower or recursive was slower. They seem to be pretty balanced speed-wise.
I looked at the disassembly and realised why they perform the same; the compiler produces the exact same assembly for both functions. I've kept this code in so you can run it yourself a few times.
So it comes down to preference. I prefer the recursive as it's less code and at a glance; easier to reason about what's happening. A lot of people don't like the ternary operator though so I can understand why the iterative version would be chosen instead.
No comments:
Post a Comment