[Performance][C#]絕對值的取得
絕對值的取得大概有兩種方法,一種是利用.NET Framework內建的Math.Abs函式;一種則是自行判斷是否為負,若為負則把它變正。稍微比較了一下兩者的速度差異,記錄如下。
測試程式碼
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
namespace WindowsFormsApplication35
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
static int ABS1(int value)
{
return value < 0 ? -value : value;
}
static int ABS2(int value)
{
return Math.Abs(value);
}
private void button1_Click(object sender, EventArgs e)
{
int count = (int)numericUpDown1.Value;
int value = -1;
textBox1.AppendText("Count: " + count.ToString() + Environment.NewLine);
Stopwatch sw = Stopwatch.StartNew();
for (int idx = 0; idx < count; ++idx)
ABS1(value);
sw.Stop();
textBox1.AppendText("ABS1: " + sw.ElapsedMilliseconds + Environment.NewLine);
sw.Reset();
sw.Start();
for (int idx = 0; idx < count; ++idx)
ABS2(value);
sw.Stop();
textBox1.AppendText("ABS2: " + sw.ElapsedMilliseconds + Environment.NewLine);
textBox1.AppendText(new string('=', 10) + Environment.NewLine);
}
}
}
測試結果
Count | ABS1 | ABS2 |
10000 | 0 | 1 |
100000 | 2 | 2 |
1000000 | 22 | 29 |
10000000 | 221 | 296 |
100000000 | 1820 | 2155 |
本來還十分不解為何會有這樣的情形,經網友提醒才注意到原來是因為少判斷了臨界值所導致。
再簡單的試驗一下,若使用checked來檢查,仍會稍微快一點。
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace ConsoleApplication31
{
class Program
{
static void Main(string[] args)
{
int count = 1000000000;
int value = -123;// -2147483648;
int absValue;
Stopwatch sw = Stopwatch.StartNew();
for (int idx = 0; idx < count; ++idx)
absValue= ABS1(value);
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
for (int idx = 0; idx < count; ++idx)
absValue=ABS2(value);
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
static int ABS1(int value)
{
checked
{
return value < 0 ? -value : value;
}
}
static int ABS2(int value)
{
return Math.Abs(value);
}
}
}
運行1000000000次的結果如下:
而若是自行用if判斷臨界值,經我測試是會變得比較慢。
經過測試,我們可以發現當不判斷臨界值時提升的效能會較為明顯,可在不會有臨界值問題的狀況下使用。像是[C#]RNGCryptoServiceProvider亂數產生器這篇下面所提的保哥的範例,使用了4個Byte來產生亂數並轉換成整數。這種情況下就不會有臨界值問題,可考慮自行撰寫程式以省略臨界值判斷。