在C#之间> 0和> = 1哪个更快更好?

Ven*_*ula 17 c# performance

在C#之间> 0和> = 1哪个更快更好?

Bil*_*eal 47

无论; 如果一个更快或更好,他们都应该编译成同样的东西.

更重要的是,大多数程序员可能会发现> 0更具可读性,可读性比这样的子微优化更重要.

  • 我不知道你的可读性断言; 我读> = 1为"1或更多",这是一种比"大于零"更自然的定义条件的方法.然而,"五个以上"在谈话中非常有意义.我认为可读性取决于上下文,以及开发人员将与代码并行查看的任何需求文档或用户指南的存在和措辞.它也在很大程度上取决于所涉及的数学类型; 正如Jesse Millikan所说,这两个比较在浮点世界中并不相同. (8认同)
  • +1表示可读性的重要性 (7认同)

Mar*_*ers 27

更好的是能够最清楚地表达你意图的那个.

如果您正在测试整数是否在[1,6]范围内,那么您应该将其写为:

 if (x >= 1 && x <= 6) { ... }
Run Code Online (Sandbox Code Playgroud)

写这个可行,但不那么明显符合规范:

 if (x > 0 && x < 7) { ... }
Run Code Online (Sandbox Code Playgroud)

我也假设你在这里讨论整数类型.如果您正在处理浮点数或十进制数,那么它们不是等价的.


除非您已经分析了代码并发现这是瓶颈,否则您不必担心微观优化.即便如此,在每种情况下检查C#编译器生成的代码以查看它们是否编译为相同的IL都是有趣的.这可以通过使用.NET Reflector来完成.

if (x >= 1)
{
    Console.WriteLine("True!");
}
Run Code Online (Sandbox Code Playgroud)

结果是:

L_000b: ldloc.0          // Load the value of x
L_000c: ldc.i4.1         // Load the constant 1 
L_000d: blt.s L_0019     // Branch if less than
L_000f: ldstr "True!"
L_0014: call void [mscorlib]System.Console::WriteLine(string)
Run Code Online (Sandbox Code Playgroud)

鉴于:

if (x > 0)
{
    Console.WriteLine("True!");
}
Run Code Online (Sandbox Code Playgroud)

得到以下IL:

L_000b: ldloc.0          // Load the value of x
L_000c: ldc.i4.0         // Load the constant 0
L_000d: ble.s L_0019     // Branch if less than or equal
L_000f: ldstr "True!"
L_0014: call void [mscorlib]System.Console::WriteLine(string)
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,编译器都颠倒了比较."大于或等于"测试编译为"小于"指令,"大于"测试编译为"小于或等于".通常,编译器可以自由地进行这样的修改,并且运行不同版本的编译器可能会产生不同的(但等效的)字节码.

鉴于它们没有编译到同一个IL,查看哪个最快的最好方法是在循环中实际运行代码并查看每个版本执行需要多长时间.我试过这样做,但我没有看到编写代码的两种方法之间存在任何可衡量的性能差异.


小智 12

没有定义的.您明确要求C# - 但这取决于处理器体系结构,即CLR运行时编译器.


Jus*_*ner 7

两者之间的性能差异可以忽略不计(如果有的话).我正在努力证明它可能是什么(它将取决于平台,因为任何不同可能会归结为由JIT发出和执行的代码).

但请记住,性能明智这是极端的微优化很可能是没有根据的.

更好的选择是更具可读性,并在代码中最好地传达您的意图.


And*_*nea 6

我同意其他回应,即通常不应考虑微优化。然而,看看这两个版本中哪一个具有更小/明显_更快的 IL 可能会很有趣。

所以 :

using System;

namespace IL_Test
{
    class Program
    {
        static void Main(string[] args)
        {
            int i = 3;
            if (i > 0)
            {
                Console.Write("i is greater than zero");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

翻译成:

(调试)

.method private hidebysig static void Main(string[] args) cil managed
{
    .entrypoint
    .maxstack 2
    .locals init (
        [0] int32 i,
        [1] bool CS$4$0000)
    L_0000: nop 
    L_0001: ldc.i4.3 
    L_0002: stloc.0 
    L_0003: ldloc.0 
    L_0004: ldc.i4.0 
    L_0005: cgt 
    L_0007: ldc.i4.0 
    L_0008: ceq 
    L_000a: stloc.1 
    L_000b: ldloc.1 
    L_000c: brtrue.s L_001b
    L_000e: nop 
    L_000f: ldstr "i is greater than zero"
    L_0014: call void [mscorlib]System.Console::Write(string)
    L_0019: nop 
    L_001a: nop 
    L_001b: ret 
}
Run Code Online (Sandbox Code Playgroud)

(释放)

.method private hidebysig static void Main(string[] args) cil managed
{
    .entrypoint
    .maxstack 2
    .locals init (
        [0] int32 i)
    L_0000: ldc.i4.3 
    L_0001: stloc.0 
    L_0002: ldloc.0 
    L_0003: ldc.i4.0 
    L_0004: ble.s L_0010
    L_0006: ldstr "i is greater than zero"
    L_000b: call void [mscorlib]System.Console::Write(string)
    L_0010: ret 
}
Run Code Online (Sandbox Code Playgroud)

尽管

using System;

namespace IL_Test
{
    class Program
    {
        static void Main(string[] args)
        {
            int i = 3;
            if (i >= 1)
            {
                Console.Write("i is greater than zero");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

进入

(调试)

.method private hidebysig static void Main(string[] args) cil managed
{
    .entrypoint
    .maxstack 2
    .locals init (
        [0] int32 i,
        [1] bool CS$4$0000)
    L_0000: nop 
    L_0001: ldc.i4.3 
    L_0002: stloc.0 
    L_0003: ldloc.0 
    L_0004: ldc.i4.1 
    L_0005: clt 
    L_0007: stloc.1 
    L_0008: ldloc.1 
    L_0009: brtrue.s L_0018
    L_000b: nop 
    L_000c: ldstr "i is greater than zero"
    L_0011: call void [mscorlib]System.Console::Write(string)
    L_0016: nop 
    L_0017: nop 
    L_0018: ret 
}
Run Code Online (Sandbox Code Playgroud)

(释放)

.method private hidebysig static void Main(string[] args) cil managed
{
    .entrypoint
    .maxstack 2
    .locals init (
        [0] int32 i)
    L_0000: ldc.i4.3 
    L_0001: stloc.0 
    L_0002: ldloc.0 
    L_0003: ldc.i4.1 
    L_0004: blt.s L_0010
    L_0006: ldstr "i is greater than zero"
    L_000b: call void [mscorlib]System.Console::Write(string)
    L_0010: ret 
}
Run Code Online (Sandbox Code Playgroud)

据我所知,在调试模式下, i>=1 比 i>0 略快

在发布模式下,所有差异都在偏移 0004 处,BLE 与 BLT。我想这两个 IL 操作转化为同样消耗 CPU 的本机操作..

  • 你说一个稍微快一点 - 你为什么不发布你的基准测试结果?你在什么机器上测试的?优化了吗?优化是由 JIT 完成的,而不是由 C# 编译器完成的,因此查看生成的 IL 并不能说明太多的性能。 (2认同)
  • @Caspar:第一个正在做:`if (i&gt;0)==false`,然后返回(不要console.write)。第二个是:`if (i&lt;1)==true`,然后返回。Andrei 测试产生的 IL 似乎比 Mark Byers 发现的要冗长得多。其他人提出的观点:运行它,对它进行基准测试,问它真的慢吗?这里的代码可能是DEBUG编译的,也可能是其他版本的编译器..我们不知道。是的,JIT 可能会优化更多,也可能不会。基准它.. (2认同)