Подтвердить что ты не робот

В С# между> 0 и >= 1, что быстрее и лучше?

В С# между > 0 и >= 1, который быстрее и лучше?

4b9b3361

Ответ 1

Ни; они оба должны скомпилировать то же самое, если один быстрее или лучше.

Более важно то, что большинство программистов, вероятно, найдут > 0 более читабельными, а читаемость более важна, чем такие микро-оптимизации, как это.

Ответ 2

Лучше тот, который наиболее четко выражает ваши намерения.

Если вы проверяете, находится ли целое число в диапазоне [1, 6], вы должны записать его как:

 if (x >= 1 && x <= 6) { ... }

Запись этого будет работать, но явно не соответствует спецификации:

 if (x > 0 && x < 7) { ... }

Я также предполагаю, что вы говорите о целых типах здесь. Если вы имеете дело с числами с плавающей запятой или десятичной точкой, они не эквивалентны.


Если вы не профилировали свой код и не обнаружили, что это узкое место, вы не должны беспокоиться о микрооптимизации. Тем не менее, может быть интересно проверить код, сгенерированный компилятором С# в каждом случае, чтобы проверить, скомпилированы ли они с тем же IL или нет. Это можно сделать, используя .NET Reflector.

if (x >= 1)
{
    Console.WriteLine("True!");
}

Результаты в:

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)

В то время как:

if (x > 0)
{
    Console.WriteLine("True!");
}

приводит к следующему 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)

В обоих случаях компилятор изменил сравнение. Тест "больше или равно" был скомпилирован с инструкцией "меньше", а тест "больше" был скомпилирован с "меньше или равно". В общем случае компилятор имеет право вносить такие изменения, и запуск другой версии компилятора может привести к другому (но эквивалентному) байт-коду.

Учитывая, что они не компилируются в один и тот же IL, лучший способ узнать, что быстрее всего, - это запустить код в цикле и посмотреть, сколько времени требуется для выполнения каждой версии. Я попытался это сделать, но я не видел никакой измеримой разницы в производительности между двумя способами написания кода.

Ответ 3

Не определено. Вы явно запрашиваете С#, но это то, что зависит от архитектуры процессора, т.е. Компилятора среды CLR.

Ответ 4

Разница в производительности будет незначительной между двумя (если она есть). Я работаю над тем, чтобы доказать, что это может быть (он будет зависящим от платформы, поскольку любой другой, вероятно, спустился бы до кода, испускаемого и исполняемого JIT).

Имейте в виду, однако, что эффективность работы - это экстремальная микро-оптимизация, скорее всего, необоснованная.

Лучший выбор - это то, что когда-либо более читаемо и передает ваши намерения лучше всего в вашем коде.

Ответ 5

Конечно, это зависит от архитектуры процессора, в которой будет работать ваша программа. На x86 инструкции jge и jg, которые здесь актуальны, принимают одинаковое количество циклов IIRC. В конкретном случае тестирования для > 0, если вы используете целые числа без знака, он может (я действительно не знаю) быстрее использовать инструкцию test вместо cmp, так как для целых чисел без знакa > 0 эквивалентно to!= 0. Другие архитектуры могут быть разными. Дело в том, что это настолько низкий уровень, что даже в редком случае, что его стоит оптимизировать, нет аппаратно-независимого способа его оптимизации.

Изменить: Забыл упомянуть: любой компилятор или виртуальная машина, заслуживающая внимания, должна выяснить, что тестирование >= 1 эквивалентно тестированию > 0 и выполнить такую ​​тривиальную оптимизацию, если она даже имеет значение на уровне языка ассемблера.

Ответ 6

Я согласен с другими ответами, что не следует принимать во внимание микрооптимизации. Однако может быть интересно посмотреть, какая из двух версий имеет меньший /visible _faster 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");
            }
        }
    }
}

Переведено на:

(ОТЛАДКА)

.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 
}

(RELEASE)

.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 
}

а

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");
            }
        }
    }
}

в

(ОТЛАДКА)

.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 
}

(RELEASE)

.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 
}

Насколько я вижу, я >= 1 немного быстрее, чем i > 0 В РЕЖИМЕ DEBUG

В режиме деблокирования все различия заключаются в смещении 0004 a BLE против BLT. Я полагаю, что эти два IL-кода преобразуются в одинаковый процессор, потребляющий собственные операционные системы.

Ответ 7

Нет никакой разницы, потому что CPU внутренне выполняет вычитание двух чисел и проверяет результат и переполнение. Для любой команды нет дополнительного шага.

Когда дело доходит до кода, это зависит от того, что вы пытаетесь документировать. >= 1 означает, что 1 является наименьшим возможным числом. > 0 означает, что 0 не допускается. Есть небольшая смысловая разница, которую могут заметить профессионалы. Они выберут правильного оператора для документирования своих намерений.

Если вы считаете, что >= n и >= n + 1 совпадают, вы ошибаетесь: >= int.MaxValue и > (int.MaxValue + 1) разные ^^

Ответ 8

Чтобы ответить быстрее, я не уверен, но я думаю, что они эквивалентны. И чтобы ответить в лучшую сторону, я думаю, что это зависит от контекста.

Ответ 9

Вы не заметите какой-либо разницы, если, возможно, в очень узкой петле, которая критична для вашего приложения. Тогда вам нужно прокомментировать ваш код, чтобы решить, что лучше.

Используйте тот, который имеет наибольший смысл в вашем приложении.

Ответ 10

Так обычно, когда я сравниваю что-то s > 0 или >= 1, я пытаюсь увидеть, содержит ли массив/коллекцию какие-либо элементы. Если это случай, вместо использования .Count > 0, попробуйте использовать вспомогательный метод Enumerable.Any() в System.Linq, который должен быть намного быстрее.

В противном случае я не знаю:)

Ответ 11

Если бы между ними была разница, то я бы сказал, что это будет такая микро-оптимизация, которая не должна влиять на общую производительность приложения.

Кроме того, когда кто-то действительно выясняет, должен ли он использовать > 0 или >= 1, я бы сказал, что стоимость для выяснения того, какая из них быстрее, не перевешивает (минимальное) преимущество в производительности.

Поэтому я бы также сказал, что вы должны использовать опцию, которая наиболее выражает намерение.