讨论一下C#面向集合的扩展

开发 后端
C#是一种面向过程的算法设计语言,在处理数学计算时显得力不从心。C#面向集合是一种比较高阶的特性,允许程序直接对集合进行直接处理,而不用显示进行循环调用,不需要指定路径,因此可以大幅提高开发效率,进行并行优化。

我们知道有很多数学软件,如MatLab是面向矩阵的,而开源语言R是面向向量的,SQL是面向关系系的、APL(Array processing language)是一种一种多用途、第三代(3GL)编程语言,在向量、矩阵等各种秩的数组处理上非常简单。SPSS,SAS等都需要大量的集合运算。

本文试图从C#本身的特性出发,模拟C#面向集合的方法。

更期望C#面向集合能向MatLab, APL,R那样直接处理集合运算,进入科学和工程计算领域,为以后的并行计算奠定基础。

有一列观测值,用List存储,我们现在需要求出每一个观测值的正弦Sin值。

用C#面向过程的语法表示如下:

  1. List list2;  
  2. for (int i = 0; i < list2.Count; i++)  
  3.             list2[i] = Math.Sin(list2[i]); 

求Sin值,是一个繁琐而又重复的问题。我们希望Math.Sin(Collection c),在不改变已有代码(不扩展Math.Sin)的情况下,自动处理集合,就像在MatLab里面。

 C#是面向过程的,而Matlab是面向矩阵的,SQL是面向关系代数的。关系代数和矩阵,都可以看作集合的特例。(LINQ部分加入了面向集合的特性)

面向过程,需要程序员书写算法的每一个过程和细节,指明执行路径,这主要表现在循环语句的使用上(包括for, foreach, while…)。

面向过程给了程序员最充分的自由和最大的灵活,但其固有的“底层”,导致了开发效率的底下,同时不利于并行计算和系统优化。而在数学中,大部分计算都是基于矩阵(集合),例如图形图像处理,概率论,数理统计,优化控制等等。 所以C#难以胜任运算集中和知识处理,人工智能设计。

由于C#实在是太优美,是目前最艺术的语言,利用C#现有特性,我们可以简单的模拟前面提出的问题    

  1. public static List Apply(Converter f, List l)  
  2.     {  
  3.        List list2 = new List(l);  
  4.         for (int i = 0; i < list2.Count; i++)  
  5.             list2[i] = Math.Sin(list2[i]);  
  6.         for (int i = 0; i < l.Count; i++)  
  7.         {  
  8.             list2[i] = f(l[i]);  
  9.         }  
  10.        return list2;  
  11.     } 

这样,我们可以在Apply来处理一些关于集合处理的问题。

下面在给出一个处理矩阵的例子:   

  1. public static Matrix Apply(Converter f, Matrix m)  
  2.     {  
  3.         Matrix m2 = new Matrix(m);  
  4.         for (int i = 0; i < m.Row; i++)  
  5.             for (int j = 0; j < m.Col; j++)  
  6.                 m2[i, j] = f(m2[i, j]);  
  7.         return m2;  

使用这个Apply,可以处理矩阵集合相关的计算。

矩阵定义如下:

  1. public class Matrix  
  2. {  
  3.     public double[,] data;  
  4.     public Matrix(int row, int col)  
  5.     {  
  6.         data = new double[row, col];  
  7.     }  
  8.     //复制构造函数  
  9.     public Matrix(Matrix m)  
  10.     {  
  11.         data = (double[,])m.data.Clone();  
  12.     }  
  13.     public int Col  
  14.     {  
  15.         get  
  16.         {  
  17.            return data.GetLength(1);  
  18.         }  
  19.     }  
  20.     // 行数  
  21.     public int Row  
  22.     {  
  23.         get  
  24.         {  
  25.             return data.GetLength(0);  
  26.         }  
  27.    }  
  28.     //重载索引  
  29.     //存取数据成员  
  30.     public virtual double this[int row, int col]  
  31.     {  
  32.         get  
  33.         {  
  34.            return data[row, col];  
  35.         }  
  36.        set  
  37.         {  
  38.             data[row, col] = value;  
  39.        }  
  40.     }  
  41.     //维数  
  42.     public int Dimension  
  43.     {  
  44.         get { return 2; }  
  45.     }  
  46.     public string ToString(int prec)  
  47.     {  
  48.         StringBuilder sb = new StringBuilder();  
  49.         string format = "{0:F" + prec.ToString() + "} ";  
  50.        for (int i = 0; i < Row; i++)  
  51.         {  
  52.             for (int j = 0; j < Col - 1; j++)  
  53.             {  
  54.                sb.Append(string.Format(format, data[i, j]));  
  55.             }  
  56.             sb.Append(data[i, Col - 1]);  
  57.             sb.Append(""n");  
  58.        }  
  59.         return sb.ToString();  
  60.     }  

再看下面复数的例子:

  1. public static List Apply(Converter< Complex,double> f, List l)  
  2.     {  
  3.         List l2 = new List(l.Count);  
  4.         for (int i = 0; i < l.Count; i++)  
  5.             l2.Add(f(l[i]));  
  6.         return l2;  

 使用这个Apply,可以处理复数集合相关的许多计算。

复数类的定义如下:

  1. Code  
  2. public class Complex:ICloneable  
  3. {  
  4.     private double real;  
  5.     /**////   
  6.    /// 复数的实部  
  7.     ///   
  8.     public double Real  
  9.     {  
  10.         get { return real; }  
  11.         set { real = value; }  
  12.    }  
  13.     private double image;  
  14.     /**////   
  15.     /// 复数的虚部  
  16.    ///   
  17.     public double Image  
  18.     {  
  19.        get { return image; }  
  20.         set { image = value; }  
  21.     }  
  22.     /**////   
  23.     /// 默认构造函数  
  24.     ///   
  25.     public Complex()  
  26.        : this(0, 0)  
  27.     {  
  28.     }  
  29.     /**////   
  30.    /// 只有实部的构造函数  
  31.     ///   
  32.     /// 实部  
  33.     public Complex(double real)  
  34.        : this(real, 0) { }  
  35.    /**////   
  36.     /// 由实部和虚部构造  
  37.     ///   
  38.     /// 实部  
  39.    /// 虚部  
  40.     public Complex(double r, double i)  
  41.     {  
  42.         rreal = r;  
  43.         iimage = i;  
  44.     }  
  45.     /**////重载加法  
  46.    public static Complex operator +(Complex c1, Complex c2)  
  47.     {  
  48.         return new Complex(c1.real + c2.real, c1.image + c2.image);  
  49.     }  
  50.     /**////重载减法  
  51.     public static Complex operator -(Complex c1, Complex c2)  
  52.     {  
  53.         return new Complex(c1.real - c2.real, c1.image - c2.image);  
  54.     }  
  55.     /**////重载乘法  
  56.     public static Complex operator *(Complex c1, Complex c2)  
  57.     {  
  58.         return new Complex(c1.real * c2.real - c1.image * c2.image, c1.image * c2.real + c1.real * c2.image);  
  59.     }  
  60.     /**////   
  61.     /// 求复数的模  
  62.     ///   
  63.     /// 模  
  64.     public double Modul  
  65.     {  
  66.         get  
  67.         {  
  68.             return Math.Sqrt(real * real + image * image);  
  69.         }  
  70.     }  
  71.     public static double Sin(Complex c)  
  72.    {  
  73.         return c.image / c.Modul;  
  74.     }  
  75.     /**////   
  76.     /// 重载ToString方法  
  77.    ///   
  78.     /// 打印字符串  
  79.     public override string ToString()  
  80.     {  
  81.         if (Real == 0 && Image == 0)  
  82.         {  
  83.             return string.Format("{0}", 0);  
  84.        }  
  85.         if (Real == 0 && (Image != 1 && Image != -1))  
  86.         {  
  87.             return string.Format("{0} i", Image);  
  88.        }  
  89.         if (Image == 0)  
  90.         {  
  91.             return string.Format("{0}", Real);  
  92.         }  
  93.         if (Image == 1)  
  94.        {  
  95.             return string.Format("i");  
  96.         }  
  97.         if (Image == -1)  
  98.         {  
  99.  
  100.            return string.Format("- i");  
  101.         }  
  102.         if (Image < 0)  
  103.         {  
  104.            return string.Format("{0} - {1} i", Real, -Image);  
  105.         }  
  106.        return string.Format("{0} + {1} i", Real, Image);  
  107.     }  
  108.    ICloneable 成员#region ICloneable 成员  
  109.   public object Clone()  
  110.     {  
  111.         Complex c = new Complex(real, image);  
  112.         return c;  
  113.     }  
  114.    #endregion  

从前面三个例子,我们可以看出,C#面向集合有多种表示方式,有.net框架中的List,也有自定义的Matrix,同时集合的元素也是多种数据类型,有系统中的值类型,也有自定义的复数Complex类型。

当然这种算法过于勉强,显然不是我们所需要的。

我们需要的是一个在不更改现有语言的情况下,不扩充Math.Sin函数(试着想想有多少个类似的函数,Cos, Tan, 我们自己定义的各种函数)。系统自动处理集合。也就是说,对于函数    public delegate TOutput Converter(TInput input);public T1 Func(T2 e); Func是Converter的实例。只要Func能够处理原子类型,那么就能处理自动所有的原子类型构成的任意集合,而不需要程序员去写多余的代码。

【编辑推荐】

  1. 在Visual Studio 2010中使用C# 4.0的动态类型
  2. C#3.0中Lambda表达式详解
  3. 浅谈C#泛型的用处
  4. 浅谈C#如何实现多继承
  5. C#实用基础教程
责任编辑:彭凡 来源: cnblogs
相关推荐

2009-07-23 11:11:18

LRU缓存

2020-07-29 10:20:28

Redis数据库字符串

2022-03-08 08:02:44

Java系统错误码

2009-08-10 17:00:14

C#分部方法

2009-08-12 16:22:29

C#插件技术

2009-08-14 10:59:35

C#分部方法

2009-11-17 11:14:25

Oracle扩展

2009-08-13 16:13:03

C#基础知识

2009-09-02 10:58:02

C#动态数组

2009-08-27 18:04:01

c#扩展方法string

2021-12-09 07:13:25

C#集合类型

2009-09-16 09:00:15

C#数组C#指针

2009-08-10 17:36:17

C#扩展方法

2009-09-01 11:04:59

C#调用扩展方法

2009-08-18 09:06:41

C#对象和集合

2009-08-31 14:45:10

C#扩展方法

2009-09-01 11:19:47

C# 3.0扩展重载抉

2011-03-25 09:08:49

C#

2009-05-08 09:46:37

微软C#集合对象

2009-05-26 11:15:31

C# 4.0dynamicVisual Stud
点赞
收藏

51CTO技术栈公众号