RE: Sleep.
Using any form of “sleep” is never as precise as you’d like it to be. Better to repeat a test multiple times.
RE: Timing Precision.
C++ and the like are designed to
permit very precise timing measurements. That does not mean that the underlying hardware/OS/whatever can be that precise. Even Windows OS functions return more precision than the vast majority of machines Windows is running on can deliver.
RE: Factorial Recursion
While that is a nicely linear recursion, it has stack-smashing possibilities: it creates a new call frame for every one of the
a
recursive invocations.
You can elide that with
tail-call optimization, or
TCO.
Do that by moving your result into arguments:
1 2 3 4
|
unsigned long long factorial( unsigned long long a, unsigned long long r = 1 )
{
return (a < 2) ? r : factorial( a-1, r*a );
}
| |
This won’t stop the answer from being incorrect after
20!
(
2,432,902,008,176,640,000
) which is as large a factorial as you can compute without overflowing a 64-bit integer. It also doesn’t stop the function from
trying to compute a larger factorial (continuing to invoke itself
a
times). But it does use only a single call frame on the stack.
You could easily write it as an explicitly iterative solution as well:
1 2 3 4 5 6 7 8 9
|
unsigned long long factorial( unsigned long long a )
{
unsigned long long r = 1;
while (a > 1)
{
r *= a--;
}
return r;
}
| |
It isn’t as pretty as the recursive solution, though.
In either case, you now don’t have to pay for a normal function call more than once and no input number can crash your program. (It can make it run a really long time, though — it is totally worth adding a condition to refuse any numbers larger than you can compute, or at least an upper limit to try computing.)