Date: 23.03.2017 3:21:45
Visual Studio 2012, оптимизация включена: вычисляется 2 раза
private void Form1_Paint(object sender, PaintEventArgs e) { e.Graphics.DrawLine(Pens.Black, 0, this.captionTextHeight + this.captionLineWidth / 2, this.Width, this.captionTextHeight + this.captionLineWidth / 2); } // Code size 67 (0x43) .maxstack 8 IL_0000: ldarg.2 IL_0001: callvirt instance class [System.Drawing]System.Drawing.Graphics [System.Windows.Forms]System.Windows.Forms.PaintEventArgs::get_Graphics() IL_0006: call class [System.Drawing]System.Drawing.Pen [System.Drawing]System.Drawing.Pens::get_Black() IL_000b: ldc.r4 0.0 IL_0010: ldarg.0 IL_0011: ldfld float32 WindowsFormsApplication1.Form1::captionTextHeight IL_0016: ldarg.0 IL_0017: ldfld float32 WindowsFormsApplication1.Form1::captionLineWidth IL_001c: ldc.r4 2. IL_0021: div IL_0022: add IL_0023: ldarg.0 IL_0024: call instance int32 [System.Windows.Forms]System.Windows.Forms.Control::get_Width() IL_0029: conv.r4 IL_002a: ldarg.0 IL_002b: ldfld float32 WindowsFormsApplication1.Form1::captionTextHeight IL_0030: ldarg.0 IL_0031: ldfld float32 WindowsFormsApplication1.Form1::captionLineWidth IL_0036: ldc.r4 2. IL_003b: div IL_003c: add IL_003d: callvirt instance void [System.Drawing]System.Drawing.Graphics::DrawLine(class [System.Drawing]System.Drawing.Pen, float32, float32, float32, float32)Поправка: вывод неверный, так как JIT дополнительно оптимизирует при выполнении, значение вычисляется один раз (см. ниже)
Date: 23.03.2017 14:37:19
А, ну да. Я забыл, что в CLR JIT занимается оптимизацией. Действительно, введение промежуточной переменной не дает выигрыша.
Тем не менее, использование умножения вместо степени, по моим измерениям, дает существенный выигрыш
class Program { const int N = 10000000; static Random r=new Random(); static double Magic(double x, double y) { return 5.1 * r.NextDouble() * x + 6.6 * r.NextDouble() * y; } static void Main(string[] args) { Stopwatch s; Random rnd; int i,k,m; double x, y,z,t; s = new Stopwatch(); rnd = new Random(); Console.WriteLine("Вычисление степени с помощью Math.Pow..."); s.Start(); for (i = 0; i < N; i++) { x = rnd.NextDouble() * 10.0; y = Math.Pow(x, 2); if (y == 100.0) Console.WriteLine("Bingo!"); } s.Stop(); Console.WriteLine("t=" + s.ElapsedMilliseconds.ToString()); s = new Stopwatch(); rnd = new Random(); Console.WriteLine("Вычисление степени с помощью умножения..."); s.Start(); for (i = 0; i < N; i++) { x = rnd.NextDouble() * 10.0; y = x * x; if (y == 100.0) Console.WriteLine("Bingo!"); } s.Stop(); Console.WriteLine("t=" + s.ElapsedMilliseconds.ToString()); /* ------------------------------------------------------------------*/ s = new Stopwatch(); rnd = new Random(); Console.WriteLine("Вычисление частного делением..."); s.Start(); for (i = 0; i < N; i++) { k = rnd.Next(); m = k / 2; if (m == 12345) Console.WriteLine("JackPot!"); } s.Stop(); Console.WriteLine("t=" + s.ElapsedMilliseconds.ToString()); s = new Stopwatch(); rnd = new Random(); Console.WriteLine("Вычисление частного сдвигом..."); s.Start(); for (i = 0; i < N; i++) { k = rnd.Next(); m = k >> 1; if (m == 12345) Console.WriteLine("JackPot!"); } s.Stop(); Console.WriteLine("t=" + s.ElapsedMilliseconds.ToString()); /* ------------------------------------------------------------------*/ s = new Stopwatch(); rnd = new Random(); Console.WriteLine("Расчет без промежуточной переменной..."); s.Start(); for (i = 0; i < N; i++) { x = rnd.NextDouble() * 10.0; y = rnd.NextDouble() * 5.0; z = Magic(x + y, x + y); if (z == 1111.11) Console.WriteLine("Magic!"); } s.Stop(); Console.WriteLine("t=" + s.ElapsedMilliseconds.ToString()); s = new Stopwatch(); rnd = new Random(); Console.WriteLine("Расчет с промежуточной переменной..."); s.Start(); for (i = 0; i < N; i++) { x = rnd.NextDouble() * 10.0; y = rnd.NextDouble() * 5.0; t=x + y; z = Magic(t, t); if (z == 1111.11) Console.WriteLine("Magic!"); } s.Stop(); Console.WriteLine("t=" + s.ElapsedMilliseconds.ToString()); Console.ReadKey(); } }
Автор: VadimTagil