#c#
#c#
Вопрос:
В приведенном ниже примере есть ли какое-либо преимущество (с точки зрения производительности) в использовании оператора меньше, чем ( < ), чтобы проверить, является ли значение отрицательным по сравнению с использованием Math.Abs?
int value = 0;
if(value < 0){
// Value is negative
}
if(Math.Abs(value) != value){
// Value is negative
}
Комментарии:
1. Я сомневаюсь, что разница будет заметна, но оператор C #
<
быстрее, чем метод .NET FrameworkMath.Abs
. Почему бы вам не проверить это самостоятельно?2. Использование `< ` vs ` != ` не имеет никакого значения для процессора. Поэтому выполнение чего-то дополнительного, а затем сравнение всегда будет медленнее.
3. @JohnHarper ты шутишь, или? Что лучше выражает «отрицательный»: «меньше 0» или «не равно его абсолютному значению»?
Ответ №1:
глядя на исходный код Abs
:
public static int Abs(int value) {
if (value >= 0)
return value;
else
return AbsHelper(value);
}
private static int AbsHelper(int value) {
Contract.Requires(value < 0, "AbsHelper should only be called for negative values! (hack for JIT inlining)");
if (value == Int32.MinValue)
throw new OverflowException(Environment.GetResourceString("Overflow_NegateTwosCompNum"));
Contract.EndContractBlock();
return -value;
}
Он не только будет медленнее, но и будет иметь другое поведение для вызова Math.Abs
вместо <
и выдаст исключение для значения Int32.MinValue
(-2147483648)
Ответ №2:
Оператор меньше, чем быстрее:
using System;
using System.Diagnostics;
namespace so64610522
{
class Program
{
static bool IsNeg1(int a)
{
return a < 0;
}
static bool IsNeg2(int a)
{
return (Math.Abs(a) != a);
}
static void Main(string[] args)
{
var min = -300000000;
var max = 300000000;
var sw = new Stopwatch();
sw.Start();
for (int i = min; i < max; i )
{
IsNeg1(i);
}
var t1 = sw.ElapsedMilliseconds;
sw.Restart();
for (int i = min; i < max; i )
{
IsNeg2(i);
}
var t2 = sw.ElapsedMilliseconds;
Console.WriteLine("{0} vs {1}", t1, t2);
}
}
}
На моей машине это выводит
1761 vs 2608
таким образом, оператор less-than на ~ 50% быстрее, чем метод abs.
Ответ №3:
Распространенный способ сравнения производительности — посмотреть, сколько операций может быть выполнено за промежуток времени. Вы могли бы легко написать что-нибудь для сравнения этих двух методов (несмотря на то, что они дают разные результаты!)
public static async Task Main()
{
var value = 100;
var result1 = await Perf(() => {var x = value < 0;});
Console.WriteLine(result1);
var result2 = await Perf(() => {var x = Math.Abs(value) != value;});
Console.WriteLine(result2);
}
static async Task<int> Perf(Action act)
{
int numOps = 0;
var cts = new CancellationTokenSource();
await Task.WhenAny(Task.Delay(2000),Task.Run(() => {
while(true)
{
act();
numOps ;
}
},cts.Token));
cts.Cancel();
return numOps;
}
Живой пример: https://dotnetfiddle.net/tgascX
Результаты, которые я получил за 2 секунды, были:
<
= 501726838Math.Abs
= 339073849
Ускорение использования <
примерно на 48%