当前位置:  开发笔记 > 编程语言 > 正文

在C#中使用泛型创建数学库

如何解决《在C#中使用泛型创建数学库》经验,为你挑选了2个好方法。

有没有可行的方法使用泛型来创建一个不依赖于选择存储数据的基类型的数学库?

换句话说,我们假设我想写一个Fraction类.该分数可以由两个整数或两个双精度或其他表示.重要的是基本的四个算术运算都有明确的定义.所以,我希望能够写Fraction frac = new Fraction(1,2)和/或Fraction frac = new Fraction(0.1, 1.0).

不幸的是,没有代表四种基本操作的接口(+, - ,*,/).有没有人找到一种可行的,可行的方法来实现这一点?



1> fryguybob..:

这是一种抽象出相对无痛的运算符的方法.

    abstract class MathProvider
    {
        public abstract T Divide(T a, T b);
        public abstract T Multiply(T a, T b);
        public abstract T Add(T a, T b);
        public abstract T Negate(T a);
        public virtual T Subtract(T a, T b)
        {
            return Add(a, Negate(b));
        }
    }

    class DoubleMathProvider : MathProvider
    {
        public override double Divide(double a, double b)
        {
            return a / b;
        }

        public override double Multiply(double a, double b)
        {
            return a * b;
        }

        public override double Add(double a, double b)
        {
            return a + b;
        }

        public override double Negate(double a)
        {
            return -a;
        }
    }

    class IntMathProvider : MathProvider
    {
        public override int Divide(int a, int b)
        {
            return a / b;
        }

        public override int Multiply(int a, int b)
        {
            return a * b;
        }

        public override int Add(int a, int b)
        {
            return a + b;
        }

        public override int Negate(int a)
        {
            return -a;
        }
    }

    class Fraction
    {
        static MathProvider _math;
        // Notice this is a type constructor.  It gets run the first time a
        // variable of a specific type is declared for use.
        // Having _math static reduces overhead.
        static Fraction()
        {
            // This part of the code might be cleaner by once
            // using reflection and finding all the implementors of
            // MathProvider and assigning the instance by the one that
            // matches T.
            if (typeof(T) == typeof(double))
                _math = new DoubleMathProvider() as MathProvider;
            else if (typeof(T) == typeof(int))
                _math = new IntMathProvider() as MathProvider;
            // ... assign other options here.

            if (_math == null)
                throw new InvalidOperationException(
                    "Type " + typeof(T).ToString() + " is not supported by Fraction.");
        }

        // Immutable impementations are better.
        public T Numerator { get; private set; }
        public T Denominator { get; private set; }

        public Fraction(T numerator, T denominator)
        {
            // We would want this to be reduced to simpilest terms.
            // For that we would need GCD, abs, and remainder operations
            // defined for each math provider.
            Numerator = numerator;
            Denominator = denominator;
        }

        public static Fraction operator +(Fraction a, Fraction b)
        {
            return new Fraction(
                _math.Add(
                  _math.Multiply(a.Numerator, b.Denominator),
                  _math.Multiply(b.Numerator, a.Denominator)),
                _math.Multiply(a.Denominator, b.Denominator));
        }

        public static Fraction operator -(Fraction a, Fraction b)
        {
            return new Fraction(
                _math.Subtract(
                  _math.Multiply(a.Numerator, b.Denominator),
                  _math.Multiply(b.Numerator, a.Denominator)),
                _math.Multiply(a.Denominator, b.Denominator));
        }

        public static Fraction operator /(Fraction a, Fraction b)
        {
            return new Fraction(
                _math.Multiply(a.Numerator, b.Denominator),
                _math.Multiply(a.Denominator, b.Numerator));
        }

        // ... other operators would follow.
    }

如果您未能实现您使用的类型,则在运行时而不是在编译时会出现故障(这很糟糕).实现的定义MathProvider总是相同的(也很糟糕).我建议您在C#中避免这样做,并使用F#或其他更适合这种抽象级别的语言.

编辑:修正了加减的定义Fraction.另一个有趣而简单的事情是实现一个在抽象语法树上运行的MathProvider.这个想法立即指向做自动分化的事情:http://conal.net/papers/beautiful-differentiation/



2> 小智..:

我相信这回答了你的问题:

http://www.codeproject.com/KB/cs/genericnumerics.aspx

推荐阅读
地之南_816
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有