討論一下C#面向集合的擴(kuò)展
我們知道有很多數(shù)學(xué)軟件,如MatLab是面向矩陣的,而開源語言R是面向向量的,SQL是面向關(guān)系系的、APL(Array processing language)是一種一種多用途、第三代(3GL)編程語言,在向量、矩陣等各種秩的數(shù)組處理上非常簡單。SPSS,SAS等都需要大量的集合運(yùn)算。
本文試圖從C#本身的特性出發(fā),模擬C#面向集合的方法。
更期望C#面向集合能向MatLab, APL,R那樣直接處理集合運(yùn)算,進(jìn)入科學(xué)和工程計(jì)算領(lǐng)域,為以后的并行計(jì)算奠定基礎(chǔ)。
有一列觀測值,用List存儲(chǔ),我們現(xiàn)在需要求出每一個(gè)觀測值的正弦Sin值。
用C#面向過程的語法表示如下:
- List list2;
- for (int i = 0; i < list2.Count; i++)
- list2[i] = Math.Sin(list2[i]);
求Sin值,是一個(gè)繁瑣而又重復(fù)的問題。我們希望Math.Sin(Collection c),在不改變已有代碼(不擴(kuò)展Math.Sin)的情況下,自動(dòng)處理集合,就像在MatLab里面。
C#是面向過程的,而Matlab是面向矩陣的,SQL是面向關(guān)系代數(shù)的。關(guān)系代數(shù)和矩陣,都可以看作集合的特例。(LINQ部分加入了面向集合的特性)
面向過程,需要程序員書寫算法的每一個(gè)過程和細(xì)節(jié),指明執(zhí)行路徑,這主要表現(xiàn)在循環(huán)語句的使用上(包括for, foreach, while…)。
面向過程給了程序員最充分的自由和最大的靈活,但其固有的“底層”,導(dǎo)致了開發(fā)效率的底下,同時(shí)不利于并行計(jì)算和系統(tǒng)優(yōu)化。而在數(shù)學(xué)中,大部分計(jì)算都是基于矩陣(集合),例如圖形圖像處理,概率論,數(shù)理統(tǒng)計(jì),優(yōu)化控制等等。 所以C#難以勝任運(yùn)算集中和知識(shí)處理,人工智能設(shè)計(jì)。
由于C#實(shí)在是太優(yōu)美,是目前最藝術(shù)的語言,利用C#現(xiàn)有特性,我們可以簡單的模擬前面提出的問題
- public static List Apply(Converter f, List l)
- {
- List list2 = new List(l);
- for (int i = 0; i < list2.Count; i++)
- list2[i] = Math.Sin(list2[i]);
- for (int i = 0; i < l.Count; i++)
- {
- list2[i] = f(l[i]);
- }
- return list2;
- }
這樣,我們可以在Apply來處理一些關(guān)于集合處理的問題。
下面在給出一個(gè)處理矩陣的例子:
- public static Matrix Apply(Converter f, Matrix m)
- {
- Matrix m2 = new Matrix(m);
- for (int i = 0; i < m.Row; i++)
- for (int j = 0; j < m.Col; j++)
- m2[i, j] = f(m2[i, j]);
- return m2;
- }
使用這個(gè)Apply,可以處理矩陣集合相關(guān)的計(jì)算。
矩陣定義如下:
- public class Matrix
- {
- public double[,] data;
- public Matrix(int row, int col)
- {
- data = new double[row, col];
- }
- //復(fù)制構(gòu)造函數(shù)
- public Matrix(Matrix m)
- {
- data = (double[,])m.data.Clone();
- }
- public int Col
- {
- get
- {
- return data.GetLength(1);
- }
- }
- // 行數(shù)
- public int Row
- {
- get
- {
- return data.GetLength(0);
- }
- }
- //重載索引
- //存取數(shù)據(jù)成員
- public virtual double this[int row, int col]
- {
- get
- {
- return data[row, col];
- }
- set
- {
- data[row, col] = value;
- }
- }
- //維數(shù)
- public int Dimension
- {
- get { return 2; }
- }
- public string ToString(int prec)
- {
- StringBuilder sb = new StringBuilder();
- string format = "{0:F" + prec.ToString() + "} ";
- for (int i = 0; i < Row; i++)
- {
- for (int j = 0; j < Col - 1; j++)
- {
- sb.Append(string.Format(format, data[i, j]));
- }
- sb.Append(data[i, Col - 1]);
- sb.Append(""n");
- }
- return sb.ToString();
- }
- }
再看下面復(fù)數(shù)的例子:
- public static List Apply(Converter< Complex,double> f, List l)
- {
- List l2 = new List(l.Count);
- for (int i = 0; i < l.Count; i++)
- l2.Add(f(l[i]));
- return l2;
- }
使用這個(gè)Apply,可以處理復(fù)數(shù)集合相關(guān)的許多計(jì)算。
復(fù)數(shù)類的定義如下:
- Code
- public class Complex:ICloneable
- {
- private double real;
- /**////
- /// 復(fù)數(shù)的實(shí)部
- ///
- public double Real
- {
- get { return real; }
- set { real = value; }
- }
- private double image;
- /**////
- /// 復(fù)數(shù)的虛部
- ///
- public double Image
- {
- get { return image; }
- set { image = value; }
- }
- /**////
- /// 默認(rèn)構(gòu)造函數(shù)
- ///
- public Complex()
- : this(0, 0)
- {
- }
- /**////
- /// 只有實(shí)部的構(gòu)造函數(shù)
- ///
- /// 實(shí)部
- public Complex(double real)
- : this(real, 0) { }
- /**////
- /// 由實(shí)部和虛部構(gòu)造
- ///
- /// 實(shí)部
- /// 虛部
- public Complex(double r, double i)
- {
- rreal = r;
- iimage = i;
- }
- /**////重載加法
- public static Complex operator +(Complex c1, Complex c2)
- {
- return new Complex(c1.real + c2.real, c1.image + c2.image);
- }
- /**////重載減法
- public static Complex operator -(Complex c1, Complex c2)
- {
- return new Complex(c1.real - c2.real, c1.image - c2.image);
- }
- /**////重載乘法
- public static Complex operator *(Complex c1, Complex c2)
- {
- return new Complex(c1.real * c2.real - c1.image * c2.image, c1.image * c2.real + c1.real * c2.image);
- }
- /**////
- /// 求復(fù)數(shù)的模
- ///
- /// 模
- public double Modul
- {
- get
- {
- return Math.Sqrt(real * real + image * image);
- }
- }
- public static double Sin(Complex c)
- {
- return c.image / c.Modul;
- }
- /**////
- /// 重載ToString方法
- ///
- /// 打印字符串
- public override string ToString()
- {
- if (Real == 0 && Image == 0)
- {
- return string.Format("{0}", 0);
- }
- if (Real == 0 && (Image != 1 && Image != -1))
- {
- return string.Format("{0} i", Image);
- }
- if (Image == 0)
- {
- return string.Format("{0}", Real);
- }
- if (Image == 1)
- {
- return string.Format("i");
- }
- if (Image == -1)
- {
- return string.Format("- i");
- }
- if (Image < 0)
- {
- return string.Format("{0} - {1} i", Real, -Image);
- }
- return string.Format("{0} + {1} i", Real, Image);
- }
- ICloneable 成員#region ICloneable 成員
- public object Clone()
- {
- Complex c = new Complex(real, image);
- return c;
- }
- #endregion
- }
從前面三個(gè)例子,我們可以看出,C#面向集合有多種表示方式,有.net框架中的List,也有自定義的Matrix,同時(shí)集合的元素也是多種數(shù)據(jù)類型,有系統(tǒng)中的值類型,也有自定義的復(fù)數(shù)Complex類型。
當(dāng)然這種算法過于勉強(qiáng),顯然不是我們所需要的。
我們需要的是一個(gè)在不更改現(xiàn)有語言的情況下,不擴(kuò)充Math.Sin函數(shù)(試著想想有多少個(gè)類似的函數(shù),Cos, Tan, 我們自己定義的各種函數(shù))。系統(tǒng)自動(dòng)處理集合。也就是說,對(duì)于函數(shù) public delegate TOutput Converter
【編輯推薦】