#c# #.net #performance #comparison #logic
#c# #.net #Производительность #сравнение #Логические
Вопрос:
Есть два логических условия :
A. ( Ls != Ec amp;amp; Ls != Uc amp;amp; Ls != Rfc )
B. (!(Ls==Ec || Ls == Uc || Ls == Rfc))
Переменными являются Ls, Ec, Uc, Rfc (целые числа)
Я обнаружил, что оба условия логически одинаковы.
Мой вопрос / ы таков (есть!) :
Существует ли какой-либо онлайн-инструмент / Сеть для проверки нескольких / двух логических условий? И с точки зрения производительности, что лучше в целом или по отношению к C # .NET 3.5
Спасибо.
Комментарии:
1. Вы обнаружили теорему Де Моргана en.wikipedia.org/wiki/Demorgan’s_theorem
2. @ Все, я знаю, что это глупый вопрос, и также не создаю никаких приложений высокого класса, но просто было любопытно узнать, существует ли какая-либо разница в производительности или нет?
Ответ №1:
В Интернете я ничего не знаю, но изучение и применение законов Де Моргана и таблиц истинности помогут вам достичь этого самостоятельно.
Комментарии:
1. отлично, спасибо. И С точки зрения производительности оба не будут иметь ни малейшей разницы?? Верно?
2. @Rahul Joshi — если нет побочных эффектов для различных условий, короткое замыкание может оказать очень незначительное влияние на производительность.
Ответ №2:
Компилятор C #, похоже, генерирует идентичный IL для обоих кодов (как при отладке, так и при сборке релиза). Следовательно, между ними не должно быть разницы в производительности.
На самом деле, согласно IL, компилятор C # переводит TestTwo в testOne. Когда вы видите скомпилированную dll в Reflector, TestTwo становится testOne.
Я скомпилировал следующий код и открыл их в ILDASM.
public bool TestOne(int l, int e, int u, int r)
{
return (l != e amp;amp; l != u amp;amp; l != r);
}
public bool TestTwo(int l, int e, int u, int r)
{
return (!(l == e || l == u || l == r));
}
Следующее — это то, что я видел в ILDASM (на основе сборки выпуска).
.method public hidebysig instance bool TestOne(int32 l,
int32 e,
int32 u,
int32 r) cil managed
{
// Code size 19 (0x13)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: beq.s IL_0011
IL_0004: ldarg.1
IL_0005: ldarg.3
IL_0006: beq.s IL_0011
IL_0008: ldarg.1
IL_0009: ldarg.s r
IL_000b: ceq
IL_000d: ldc.i4.0
IL_000e: ceq
IL_0010: ret
IL_0011: ldc.i4.0
IL_0012: ret
} // end of method Program::TestOne
.method public hidebysig instance bool TestTwo(int32 l,
int32 e,
int32 u,
int32 r) cil managed
{
// Code size 19 (0x13)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: beq.s IL_0011
IL_0004: ldarg.1
IL_0005: ldarg.3
IL_0006: beq.s IL_0011
IL_0008: ldarg.1
IL_0009: ldarg.s r
IL_000b: ceq
IL_000d: ldc.i4.0
IL_000e: ceq
IL_0010: ret
IL_0011: ldc.i4.0
IL_0012: ret
} // end of method Program::TestTwo
Я использовал VS2008 sp1 (.NET 3.5 sp1) для тестирования этого кода.
Ответ №3:
Есть поговорка «Сначала заставь это работать, затем сделай это быстро!». Я бы предположил, что разница (если она вообще существует) между обеими версиями не повлияет на общую производительность вашего приложения — по крайней мере, в 99,99% всех приложений. Если ваше приложение входит в число оставшихся 0,001%, то вы пишете очень особенное и сложное высокоскоростное программное обеспечение. В этом случае вам не следует использовать теоретические инструменты. Измерьте это в реальных условиях!
Ответ №4:
Я считаю, что это зависит от реализации…
На a .Платформа на основе сети, насколько я помню, при использовании оператора amp;amp; выражение вычисляется слева направо, и если левый операнд равен false, правый даже не вычисляется. Исходя из этой логики, я чувствую, что вариант A был бы выбран и быстрее, если бы один из этих самых левых операндов оказался ложным. Я предполагаю, что это может быть причиной, по которой IL generated предпочитает использовать метод testOne (Кстати, отличная идея определить, каков выбранный путь, спасибо Chansik Im.