2分割は/2か*0.5のどっちが早いんだべいべぇという話がありました。
http://blogs.wankuma.com/zee/archive/2006/12/22/52811.aspx
まぁ読みにくいから0.5はないよねってのは当然として、検証しなくちゃだめだめよ。
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
for (int loopcounter = 0; loopcounter < 999999; loopcounter++)
{
fnca();
fncb();
fncc();
}
}
public static int fnca()
{
int i = 1;
return (int)(i / 2);
}
public static int fncb()
{
int i = 1;
return (int)(i * 0.5);
}
public static int fncc()
{
int i = 1;
return (int)(i >> 1);
}
}
}
まず/2と0.5の計算は等価じゃないってことを把握してください。
0.5はintではなくdoubleです。
ConsoleApplication1.Program.fncb() 999999 38.638239
ConsoleApplication1.Program.fnca() 999999 30.913036
ConsoleApplication1.Program.fncc() 999999 29.697814
これがVS2005のプロファイラでの結果。
一番早いのはfnccで、次点がfnca。
もちろん検証はこんなところで終っちゃ名がすたる。
ILを見てください。
そんなに難しくないので、リリース版ILにしちゃいます。違いは読み取ってね。
.method public hidebysig static int32 fnca() cil managed
{
.maxstack 2
.locals init (
[0] int32 num1)
L_0000: ldc.i4.1
L_0001: stloc.0
L_0002: ldloc.0
L_0003: ldc.i4.2
L_0004: div
L_0005: ret
}
.method public hidebysig static int32 fncb() cil managed
{
.maxstack 2
.locals init (
[0] int32 num1)
L_0000: ldc.i4.1
L_0001: stloc.0
L_0002: ldloc.0
L_0003: conv.r8
L_0004: ldc.r8 0.5
L_000d: mul
L_000e: conv.i4
L_000f: ret
}
.method public hidebysig static int32 fncc() cil managed
{
.maxstack 2
.locals init (
[0] int32 num1)
L_0000: ldc.i4.1
L_0001: stloc.0
L_0002: ldloc.0
L_0003: ldc.i4.1
L_0004: shr
L_0005: ret
}
んで本当のアセンブリ
public static int fnca()
{
int i = 1;
00000000 sub rsp,38h
00000004 mov dword ptr [rsp+20h],0
0000000c mov rax,642801A2118h
00000016 mov eax,dword ptr [rax]
00000018 test eax,eax
0000001a je 0000000000000021
0000001c call FFFFFFFFFF7887A0
00000021 mov dword ptr [rsp+20h],1
return (int)(i / 2);
00000029 mov eax,dword ptr [rsp+20h]
0000002d cdq
0000002e sub eax,edx
00000030 sar eax,1
00000032 mov dword ptr [rsp+24h],eax
00000036 mov eax,dword ptr [rsp+24h]
0000003a jmp 000000000000003C
0000003c add rsp,38h
00000040 rep ret
public static int fncb()
{
int i = 1;
00000000 sub rsp,38h
00000004 mov dword ptr [rsp+20h],0
0000000c mov rax,642801A2118h
00000016 mov eax,dword ptr [rax]
00000018 test eax,eax
0000001a je 0000000000000021
0000001c call FFFFFFFFFF7884F0
00000021 mov dword ptr [rsp+20h],1
return (int)(i * 0.5);
00000029 cvtsi2sd xmm0,dword ptr [rsp+20h]
0000002f mulsd xmm0,mmword ptr [00000070h]
00000037 cvttsd2si eax,xmm0
0000003b jmp 000000000000003D
0000003d add rsp,38h
00000041 rep ret
public static int fncc()
{
int i = 1;
00000000 sub rsp,38h
00000004 mov dword ptr [rsp+20h],0
0000000c mov rax,642801A2118h
00000016 mov eax,dword ptr [rax]
00000018 test eax,eax
0000001a je 0000000000000021
0000001c call FFFFFFFFFF788460
00000021 mov dword ptr [rsp+20h],1
return (int)(i >> 1);
00000029 mov eax,dword ptr [rsp+20h]
0000002d sar eax,1
0000002f jmp 0000000000000031
00000031 add rsp,38h
00000035 rep ret
む。クロック数がわからん。
でも、ctvsi2sdなんていう命令使って最適化は行っているですねぇ。