C# 这些操作是否等效?

C# 这些操作是否等效?,c#,algorithm,C#,Algorithm,我正在重构一些代码,我偶然发现了这样一段话 if (a > 1.0) a = 1.0; else if (a < -1.0) a = -1.0; if (Math.Abs(a) > 1.0) a = a < 0 ? -1.0 : 1.0; if(a>1.0) a=1.0; 否则如果(a1.0) a=a1.0) a=1.0; 否则如果(a1.0) a=a1.0) 000000 2B fld qword ptr[ebp+8] 0000002e fld1 000

我正在重构一些代码,我偶然发现了这样一段话

if (a > 1.0)
  a = 1.0;
else if (a < -1.0)
  a = -1.0;
if (Math.Abs(a) > 1.0)
  a = a < 0 ? -1.0 : 1.0;
if(a>1.0)
a=1.0;
否则如果(a<-1.0)
a=-1.0;
根据我们的指导原则,我应该把它重构成这样的东西

if (a > 1.0)
  a = 1.0;
else if (a < -1.0)
  a = -1.0;
if (Math.Abs(a) > 1.0)
  a = a < 0 ? -1.0 : 1.0;
if(数学Abs(a)>1.0)
a=a<0-1.0 : 1.0;
当然,只有在不改变语句逻辑的情况下才允许重构。我已经看完了,没有发现任何偏差或差异。我还编写并运行了一系列测试,试图找出那些棘手而尖锐的案例。一切似乎都很好

然后,一位同事在工作时偷看了一眼,用一种非常毒的语气暗示说那里有东西痒。他本来应该在第二天透露这个大秘密的,但后来他生病了,现在正在度假


几天来我一直在盯着这些线看。我睡过了。我已经试过了所有的窍门。没有什么!所以要么我没本事看,要么他就是个耍恶作剧的混蛋。我需要帮助确定。

是的,它们是一样的Update:但不能使用大小写
Int.MinValue
\
Long.MinValue
等,因为
Math.Abs
会抛出一个
溢出异常
-谢谢@SledgeHammer/@Quantic!-所以这可能就是问题所在

方法相同的“证明”(减去溢出)

这与:(写出
Math.Abs

删除死代码:

if (a > 1.0)
{
    if (a >= 0) //else
    {
        a = 1.0;
    }
}
else if (a < -1.0)
{
    if (a < 0)
    {
        a = -1.0;
    }
}
完成:)

PS:为了便于阅读,如果愿意:

if (a > 1.0)
  a = 1.0;
else if (a < -1.0)
  a = -1.0;
Math.Abs(a)
相当于(参见)

if (a >= 0)
{
    return a;
}
else
{
    return -a;
}
因此,增加了以下条件:

if (a >= 0)
{
    return a > 1.0;
}
else
{

    return (-a) > 1.0;
}
if (a >= 0)
{
    return a > 1.0;
}
else
{
    return a < -1.0;
}
重写条件:

if (a >= 0)
{
    return a > 1.0;
}
else
{

    return (-a) > 1.0;
}
if (a >= 0)
{
    return a > 1.0;
}
else
{
    return a < -1.0;
}

是的,它们是一样的Update:但不能使用大小写
Int.MinValue
\
Long.MinValue
等,因为
Math.Abs
会抛出一个
溢出异常
-谢谢@SledgeHammer/@Quantic!-所以这可能就是问题所在

方法相同的“证明”(减去溢出)

这与:(写出
Math.Abs

删除死代码:

if (a > 1.0)
{
    if (a >= 0) //else
    {
        a = 1.0;
    }
}
else if (a < -1.0)
{
    if (a < 0)
    {
        a = -1.0;
    }
}
完成:)

PS:为了便于阅读,如果愿意:

if (a > 1.0)
  a = 1.0;
else if (a < -1.0)
  a = -1.0;
Math.Abs(a)
相当于(参见)

if (a >= 0)
{
    return a;
}
else
{
    return -a;
}
因此,增加了以下条件:

if (a >= 0)
{
    return a > 1.0;
}
else
{

    return (-a) > 1.0;
}
if (a >= 0)
{
    return a > 1.0;
}
else
{
    return a < -1.0;
}
重写条件:

if (a >= 0)
{
    return a > 1.0;
}
else
{

    return (-a) > 1.0;
}
if (a >= 0)
{
    return a > 1.0;
}
else
{
    return a < -1.0;
}
说明了为什么它们在概念上是相同的,所以我将深入研究它们的内部

我编写了一个小测试程序,然后查看了反汇编(Visual Studio 2012)

类程序
{
静态空隙A(双A)
{
如果(a>1.0)
a=1.0;
否则如果(a<-1.0)
a=-1.0;
}
静态空隙B(双a)
{
如果(数学Abs(a)>1.0)
a=a<0?-1.0:1.0;
}
静态void Main(字符串[]参数)
{
A(-1.17);
B(-1.17);
}
}
A的结果

            if (a > 1.0)
0000002b  fld         qword ptr [ebp+8] 
0000002e  fld1 
00000030  fcomip      st,st(1) 
00000032  fstp        st(0) 
00000034  jp          0000003A 
00000036  jb          0000003E 
00000038  jmp         0000003A 
0000003a  xor         eax,eax 
0000003c  jmp         00000043 
0000003e  mov         eax,1 
00000043  test        eax,eax 
00000045  sete        al 
00000048  movzx       eax,al 
0000004b  mov         dword ptr [ebp-3Ch],eax 
0000004e  cmp         dword ptr [ebp-3Ch],0 
00000052  jne         0000005C 
                a = 1.0;
00000054  fld1 
00000056  fstp        qword ptr [ebp+8] 
00000059  nop 
0000005a  jmp         00000092 
            else if (a < -1.0)
0000005c  fld         qword ptr [ebp+8] 
0000005f  fld         dword ptr ds:[001D2F50h] 
00000065  fcomip      st,st(1) 
00000067  fstp        st(0) 
00000069  jp          0000006F 
0000006b  ja          00000073 
0000006d  jmp         0000006F 
0000006f  xor         eax,eax 
00000071  jmp         00000078 
00000073  mov         eax,1 
00000078  test        eax,eax 
0000007a  sete        al 
0000007d  movzx       eax,al 
00000080  mov         dword ptr [ebp-3Ch],eax 
00000083  cmp         dword ptr [ebp-3Ch],0 
00000087  jne         00000092 
                a = -1.0;
00000089  fld         dword ptr ds:[001D2F58h] 
0000008f  fstp        qword ptr [ebp+8] 
if(a>1.0)
000000 2B fld qword ptr[ebp+8]
0000002e fld1
000000 30 fcomip街,街(1)
00000032 fstp st(0)
00000034日元0000003A
000000 36 jb 000000 3E
000000 38 jmp 000000 3A
0000003a异或eax,eax
000000 3C jmp 000000 43
0000003e mov eax,1
00000043测试eax,eax
00000045塞特艾尔
000000 48 movzx eax,al
000000 4B mov dword ptr[ebp-3Ch],eax
0000004e cmp dword ptr[ebp-3Ch],0
00000052 jne 0000005C
a=1.0;
00000054 fld1
00000056 fstp qword ptr[ebp+8]
00000059无
000000 5A jmp 000000 92
否则如果(a<-1.0)
000000 5C fld qword ptr[ebp+8]
000000 5F fld dword ptr ds:[001D2F50h]
00000065 fcomip街,街(1)
00000067 fstp st(0)
00000069JP0000006F
0000006b ja 00000073
0000006d jmp 0000006F
0000006f异或eax,eax
000000 71 jmp 000000 78
00000073 mov eax,1
00000078测试eax,eax
0000007a塞特艾尔
000000 7D movzx eax,al
000000 80 mov德沃德ptr[ebp-3Ch],eax
000000 83 cmp dword ptr[ebp-3Ch],0
00000087 jne 00000092
a=-1.0;
000000 89 fld dword ptr ds:[001D2F58h]
000000 8F fstp qword ptr[ebp+8]
总数:38项指示

B的结果

            if (Math.Abs(a) > 1.0)
0000002b  fld         qword ptr [ebp+8] 
0000002e  sub         esp,8 
00000031  fstp        qword ptr [esp] 
00000034  call        749B481F 
00000039  fstp        qword ptr [ebp-44h] 
0000003c  fld         qword ptr [ebp-44h] 
0000003f  fld1 
00000041  fcomip      st,st(1) 
00000043  fstp        st(0) 
00000045  jp          0000004B 
00000047  jb          0000004F 
00000049  jmp         0000004B 
0000004b  xor         eax,eax 
0000004d  jmp         00000054 
0000004f  mov         eax,1 
00000054  test        eax,eax 
00000056  sete        al 
00000059  movzx       eax,al 
0000005c  mov         dword ptr [ebp-3Ch],eax 
0000005f  cmp         dword ptr [ebp-3Ch],0 
00000063  jne         0000008A 
                a = a < 0 ? -1.0 : 1.0;
00000065  fld         qword ptr [ebp+8] 
00000068  fldz 
0000006a  fcomip      st,st(1) 
0000006c  fstp        st(0) 
0000006e  jp          00000072 
00000070  ja          0000007A 
00000072  nop 
00000073  fld1 
00000075  fstp        qword ptr [ebp-4Ch] 
00000078  jmp         00000083 
0000007a  fld         dword ptr ds:[001D3008h] 
00000080  fstp        qword ptr [ebp-4Ch] 
00000083  nop 
00000084  fld         qword ptr [ebp-4Ch] 
00000087  fstp        qword ptr [ebp+8]
if(数学Abs(a)>1.0)
000000 2B fld qword ptr[ebp+8]
000000 2E子esp,8
000000 31 fstp qword ptr[esp]
00000034呼叫749B481F
000000 39 fstp qword ptr[ebp-44h]
000000 3C fld qword ptr[ebp-44h]
0000003f fld1
000000 41 fcomip街,街(1)
000000 43 fstp st(0)
000000 45日元000000 4b
000000 47 jb 000000 4F
000000 49 jmp 000000 4B
0000004b异或eax,eax
000000 4D jmp 000000 54
000000 4F mov eax,1
00000054测试eax,eax
00000056塞特艾尔
000000 59 movzx eax,al
000000 5C mov dword ptr[ebp-3Ch],eax
000000 5F cmp dword ptr[ebp-3Ch],0
00000063 jne 0000008A
a=a<0-1.0 : 1.0;
000000 65 fld qword ptr[ebp+8]
00000068 fldz
000000 6A fcomip街,街(1)
000000 6C fstp st(0)
0000006e日元00000072
00000070ja0000007a
00000072无
00000073 fld1
00000075 fstp qword ptr[ebp-4Ch]
00000078 jmp 00000083
000000 7A fld dword ptr ds:[001D3008h]
000000 80 fstp qword ptr[ebp-4Ch]
00000083无
000000 84 fld qword ptr[ebp-4Ch]
00000087 fstp qword ptr[ebp+8]
总计:36条指令+对Math.Abs的函数调用

结果: 第一个可能要快一点,但它们的大小非常接近,很难想象使用一个而不是另一个会严重影响性能。我个人同意你的评论,你的原始版本在概念上更容易理解

编辑<