What is the more efficient syntax for creating an even number in my console project?

I recently started to learn C # and found out that there are two ways for my code to output even numbers when I write this For loop . I learned the syntax of version 2, which is intuitive to me. However, version 1 was a check that I found elsewhere on the Internet. I want to understand if there is a difference between the two versions.

 //Version 1 for (int num = 0; num < 100; num+=2) { Console.WriteLine (num); } //Version 2 for (int num = 0; num < 100; num++) { if (num % 2 == 0) { Console.WriteLine (num); } } 

Of the two possible ways, is there a difference between the two syntaxes? If so, which is more effective and why?

+6
source share
7 answers

For a given value of N (in your code example, N = 100)

  • Version # 1 adds N/2
  • Version 2 adds N , plus N integer divisions (relatively expensive operation).

And you forgot Version 3, bit tricks. Bitwise operations are much cheaper than division, and since we know that integers in the C # world are binary values ​​of a binary complement, the state of the least significant bit tells us whether the integer is even or not, thus:

 bool isEven( int n ) { return 0 == ( n & 1 ) ; } 

We can write a test harness, for example:

 class Program { public static int Version1(int n) { int cnt = 0; for ( int i = 0 ; i < n ; i+=2 ) { ++cnt; } return cnt; } public static int Version2(int n) { int cnt = 0; for ( int i = 0 ; i < n ; ++i ) { if ( i % 2 == 0 ) { ++cnt; } } return cnt; } public static int Version3(int n) { int cnt = 0; for ( int i = 0 ; i < n ; ++i ) { if ( 0 == (i & 1) ) { ++cnt; } } return cnt; } private static void Main(string[] args) { int n = 500000000; Stopwatch timer = new Stopwatch(); timer.Start(); Version1( n ); timer.Stop(); Console.WriteLine( "{0:c} -- Version #1 (incrementing by 2)" , timer.Elapsed ) ; timer.Restart(); Version2(n); timer.Stop(); Console.WriteLine( "{0:c} -- Version #2 (incrementing by 1 with modulo test)" , timer.Elapsed ) ; timer.Restart(); Version3(n); timer.Stop(); Console.WriteLine( "{0:c} -- Version #3 (incrementing by 1 with bit twiddling)" , timer.Elapsed ) ; return; } } 

And find out what is actually faster. The above program starts the cycle 500,000,000 times, so we get numbers that are large enough to measure.

Here are the timings I get with VS 2013:

  • Assembly debugging (not optimized):

     00:00:00.5500486 -- Version #1 (incrementing by 2) 00:00:02.0843776 -- Version #2 (incrementing by 1 with modulo test) 00:00:01.2507272 -- Version #3 (incrementing by 1 with bit twiddling) 
    • Version # 2 3,789 times slower than version # 1
    • Version # 3 2.274 times slower than version # 1
  • Create assembly (optimized)

     00:00:00.1680107 -- Version #1 (incrementing by 2) 00:00:00.5109271 -- Version #2 (incrementing by 1 with modulo test) 00:00:00.3367961 -- Version #3 (incrementing by 1 with bit twiddling) 
    • Version # 2 3.041 times slower than version # 1
    • Version # 3 2.005 times slower than version # 1
+5
source

Version 1 is “faster” in terms of pure analysis (regardless of compilation optimization). But since dbarnes is mentioned in the comments on your question, what you code in C # and what comes out on the other side of the compiler may be completely different. Version 2 is “slower” because it has more iteration loops for looping, and with this if-statement has a bit more code complexity.

Do not worry about optimizations too high at first (this is called "premature optimization" to deal with performance before you know that it exists and can prove that it is a problem that is worth solving), Just code to study, and then refactoring and then look at performance issues, if any.

In fact, I would suggest that the compiler can be set to “expand” both of these loops: it gets rid of the loop and simply duplicates the loop body 50 or 100 times for version 1 or 2, respectively.

+3
source

You can pinpoint which method is faster, with an accuracy of the 10,000th millisecond, also known as “Tick” in the .Net infrastructure.

This is done using the Stopwatch class in the System.Diagnostic namespace:

 var sw1 = new System.Diagnostics.Stopwatch(); var sw2 = new System.Diagnostics.Stopwatch(); //Version 1 sw1.Start(); for (int num = 0; num < 100; num += 2) { Console.WriteLine(num); } sw1.Stop(); //Version 2 sw2.Start(); for (int num = 0; num < 100; num++) { if (num % 2 == 0) { Console.WriteLine(num); } } sw2.Stop(); Console.Clear(); Console.WriteLine("Ticks for first method: " + sw1.ElapsedTicks); Console.WriteLine("Ticks for second method: " + sw2.ElapsedTicks); 

The output will show that the first method is faster.

Why is this so? In the first version, ignoring the console output, only one operation is performed ( += 2 ), and at the end the program performs 50 cycle cycles.

In the second version, you need to perform two operations ( ++ and % 2 ) and one more comparison ( num % 2 == 0 ) in addition to 100 cycles in a cycle.

If you measure the program in the same way, then it will have a big time difference, for example, a few milliseconds. This is because Console.WriteLine actually takes a lot of time. Since the second version did it 50 times more, it takes much more time. If you want to measure only one algorithm, omit the console output.

If you do, the tick difference on my machine averages 24 ticks to 43 ticks.

So, in conclusion, the first method is about 19/10000 milliseconds more efficient.

+3
source

Actually the add mechanism (version 1) is slightly better

The result of the addition was better than the modulus (%) by 0.0070000 milliseconds for 2 million or 200,000 iterations

But seriously, if you don’t have a critical need for micro-optimization, stick with the module operator for easy code reading, rather than trying to save about 00.0070000 milliseconds of execution time.

Here is the source

+2
source

Version 1 is more efficient in the sense that it iterates in half with the same output. Version 1 will iterate 50 times, when version 2 will repeat 100 times, but only print half the results. However, I think the second shows your intentions better.

+1
source

Version 1 is more efficient. Since “version 2” takes up one more comparison than “version 1”, while “version 1” takes two comparisons.

 //Version 1 for (int num = 0; num < 100; num+=2) // Two comparisons { Console.WriteLine (num); } //Version 2 for (int num = 0; num < 100; num++) // Two comparisons { if (num % 2 == 0) // One comparison { Console.WriteLine (num); } } 
+1
source

This method is faster than method 1 and method 2, because recursion is faster than a loop.

  var sw3 = new System.Diagnostics.Stopwatch(); Action<int, int> printEvens = null; printEvens = (index, count) => { if (index % 2 == 0) Console.WriteLine(index.ToString()); if (index < count) printEvens(++index, count); }; sw3.Start(); printEvens(0, 100); sw3.Stop(); 

The output on my computer is this.

Method 1: 96282 Method 2: 184336 Method 3: Recursion 59188

0
source

All Articles