C#面向集合的扩展(讨论)

原创|其它|编辑:郝浩|2009-07-06 11:03:30.000|阅读 355 次

概述:C#是一种面向过程的算法设计语言,在处理数学计算时显得力不从心。面向集合是一种比较高阶的特性,允许程序直接对集合进行直接处理,而不用显示进行循环调用,不需要指定路径,因此可以大幅提高开发效率,进行并行优化。很多数学软件,如MatLab是面向矩阵的,而开源语言R是面向向量的,SQL是面向关系系的、APL(Array processing language)是一种一种多用途、第三代(3GL)编程语言,在向量、矩阵等各种秩的数组处理上非常简单。SPSS,SAS等都需要大量的集合运算。

# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>

问题引出

C#是一种面向过程的算法设计语言,在处理数学计算时显得力不从心。面向集合是一种比较高阶的特性,允许程序直接对集合进行直接处理,而不用显示进行循环调用,不需要指定路径,因此可以大幅提高开发效率,进行并行优化。很多数学软件,如MatLab是面向矩阵的,而开源语言R是面向向量的,SQL是面向关系系的、APL(Array processing language)是一种一种多用途、第三代(3GL)编程语言,在向量、矩阵等各种秩的数组处理上非常简单。SPSS,SAS等都需要大量的集合运算。

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

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

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

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

List<double> list2;

for (int i = 0; i < list2.Count; i++)

            list2[i] 
= Math.Sin(list2[i]);

 

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

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

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

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

Apply来处理一些关于集合处理的问题。


public static List<double> Apply(Converter<doubledouble> f, List<double> l)

    
{

        List
<double> list2 = new List<double>(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,可以处理矩阵集合相关的计算。


public static Matrix Apply(Converter<doubledouble> 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;

}

使用这个

矩阵定义如下: 

 


public class Matrix

{

    
public double[,] data;

 

    
public Matrix(int row, int col)

    
{

        data 
= new double[row, col];

    }


    
//复制构造函数

    
public Matrix(Matrix m)

    
{

        data 
= (double[,])m.data.Clone();

    }


    
public int Col

    
{

        
get

        
{

            
return data.GetLength(1);

        }


    }


    
// 行数

    
public int Row

    
{

        
get

        
{

            
return data.GetLength(0);

        }


    }


    
//重载索引

    
//存取数据成员

    
public virtual double this[int row, int col]

    
{

        
get

        
{

            
return data[row, col];

        }


        
set

        
{

            data[row, col] 
= value;

        }


    }


    
//维数

    
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();

    }


}


 

再看下面复数的例子:


public static List<double> Apply(Converter< Complex,double> f, List<Complex> l)

    
{

        List
<double> l2 = new List<double>(l.Count);

        
for (int i = 0; i < l.Count; i++)

            l2.Add(f(l[i]));

        
return l2;

}


   

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

复数类的定义如下: 

.net框架中的List,也有自定义的Matrix,同时集合的元素也是多种数据类型,有系统中的值类型,也有自定义的复数Complex类型。 


public class Complex:ICloneable

{

    
private double real;

    
/// <summary>

    
/// 复数的实部

    
/// </summary>


    
public double Real

    
{

        
get return real; }

        
set { real = value; }

    }


 

    
private double image;

    
/// <summary>

    
/// 复数的虚部

    
/// </summary>


    
public double Image

    
{

        
get return image; }

        
set { image = value; }

    }


 

 

    
/// <summary>

    
/// 默认构造函数

    
/// </summary>


    
public Complex()

        : 
this(00)

    
{

    }


 

    
/// <summary>

    
/// 只有实部的构造函数

    
/// </summary>

    
/// <param name="real">实部</param>


    
public Complex(double real)

        : 
this(real, 0{ }

 

    
/// <summary>

    
/// 由实部和虚部构造

    
/// </summary>

    
/// <param name="real">实部</param>

    
/// <param name="image">虚部</param>


    
public Complex(double r, double i)

    
{

        real 
= r;

        image 
= 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);

    }


 

    
/// <summary>

    
/// 求复数的模

    
/// </summary>

    
/// <returns></returns>


    
public double Modul

    
{

        
get

        
{

            
return Math.Sqrt(real * real + image * image);

        }


    }


 

    
public static double Sin(Complex c)

    
{

        
return c.image / c.Modul;

    }


    
/// <summary>

    
/// 重载ToString方法

    
/// </summary>

    
/// <returns>打印字符串</returns>


    
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 成员

}


 

从前面三个例子,我们可以看出,集合有多种表示方式,有

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

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


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com

文章转载自:博客园

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP