No no.
That is not OK.
You can't accurately measure time intervals below one microsecond like that; first of all the system clock doesn't have that fine a resolution, then getting DateTime.Now has a cost involved, and finally there is no guarantee your code will not be interrupted by the OS.
You really must create a loop that executes the same thing many times, and
time the overall loop, then divide. And yes, this makes it more likely to catch some system event, however it will give better real-life values.
I tend to loop for many milliseconds, then use TimeSpan.TotalMilliSeconds.
I avoid using Ticks, those are computer units that may vary by hardware and/or OS.
Even when ticks have a resolution of one tenth of a microsecond, that does not imply the
tick count will be incremented by one every tenth of a microsecond. It may well be incremented by a larger number at a lower frequency.
My very
first and old article[
^] here on CodeProject discussed some of such timer behavior.
So remove everything time related from your code under test, then create a loop and surround that with your time measurement stuff.
I'm not sure what goes wrong in your isPrime2 time measurement, your code is rather convoluted.
When I run similar tests on my machine, I'm getting 2000 msec twice for 10000 iterations (both in Debug and Release mode); the difference between tests 1 and 2 is negligible, and certainly less than the timing inaccuracy for the given test case. With random values, isPrime2 will be faster of course.
This is part of the code I ran:
static bool test1(int p) {
bool isPrime = false;
DateTime start = DateTime.Now;
for (int i = 0; i < 10000; i++) {
isPrime = IsPrime1(p);
}
DateTime end = DateTime.Now;
TimeSpan span = end - start;
Console.WriteLine("IsPrime1: {0} is {1}a prime ({2} ms) ", p, isPrime ? "" : "not ", span.TotalMilliseconds);
return isPrime;
}
PS: you have an i++ in your for loop; as you start with 3, you'd better use i+=2 skipping all even candidate divisors. (isPrime1 should report 2 being prime though, which it currently does not).
ADDED:
This code helps in understanding how Ticks work:
static void observeTicks() {
Console.WriteLine("What is the typical increment of Ticks?");
for (int i = 0; i < 10; i++) {
long ticks0 = DateTime.Now.Ticks;
while (true) {
long tickStep = DateTime.Now.Ticks - ticks0;
if (tickStep != 0) {
Console.WriteLine("tickStep=" + tickStep);
break;
}
}
}
Console.WriteLine("What is the absolute value of 1,000,000 Ticks?");
DateTime start = DateTime.Now;
long weWillExitAt = start.Ticks+1000000;
DateTime end = DateTime.Now;
while (true) {
end = DateTime.Now;
if (end.Ticks >= weWillExitAt) break;
}
TimeSpan span = end - start;
Console.WriteLine("1,000,000 Ticks = {0} msec", span.TotalMilliseconds);
}
On my system, ticks correspond to a tenth of a microsecond, and tickStep typically is around 10000, i.e. 1 msec. Your isPrime test case takes about 0.2 msec, meaning you have 80% probability of measuring zero time and 20% of measuring 1 msec. Now whenever your program somehow synchronizes to the system clock, specific parts of it may tend to fall early or late in a tick, resulting in a lower or higher probability to yield a non-zero time measurement.
Synchronization might occur at program launch, at every Console operation, at many I/O operations, etc.
If you were to execute something like
Thread.Sleep(1);
...isPrime1(p)...
Thread.Sleep(1);
...isPrime2(p)...
Thread.Sleep(1);
...isPrime1(p)...
Thread.Sleep(1);
...isPrime2(p)...
I expect you'll get many more zero times.