9

次のコードは非常に反復的です。

 public static double Interpolate(double x1, double y1, double x2, double y2, double x)
    {
        return y1 + (x - x1) * (y2 - y1) / (x2 - x1);
    }
    public static decimal Interpolate(decimal x1, decimal y1, decimal x2, decimal y2, decimal x)
    {
        return y1 + (x - x1) * (y2 - y1) / (x2 - x1);
    }

ただし、ジェネリックを使用しようとするとコンパイルされません。

 public static T Interpolate<T>(T x1, T y1, T x2, T y2, T x)
    {
        return y1 + (x - x1) * (y2 - y1) / (x2 - x1);
    }

エラーメッセージは次のとおりです。

エラー 2 演算子 '-' は型 'T' および 'T' C:\Git...\LinearInterpolator.cs のオペランドに適用できません

コードを再利用するにはどうすればよいですか?

編集:このモジュールでは、高速ランタイムが重要です。

4

4 に答える 4

4

現在のコードはそのままで問題ありません。おそらく、double を decimal にキャストせずに達成できる最高のものです。

一般的な解決策は可能ですが、非常に多くのインフラストラクチャが必要になるため、物事が複雑になりすぎます。

于 2012-04-24T16:02:16.147 に答える
4

これを行う必要があるときはいつでも、私は単に に頼っていdynamicます。これは問題なく動作しますが、現在のオーバーロードよりも多少遅くなる可能性があります。

 public static T Interpolate<T>(T x1, T y1, T x2, T y2, T x)
 {         
     return y1 + ((dynamic)x - x1) * ((dynamic)y2 - y1) / ((dynamic)x2 - x1);
 }
于 2012-04-24T16:07:56.890 に答える
3

で基本クラスの制約を指定しないと、ジェネリックで演算子を使用できませんT

次のようなことをするかもしれません: C# で Generics を使用して数学ライブラリを作成しますが、個人的には、実際に多くの異なる数式を使用しない限り、あまり意味がありません。

の式ツリーを動的にコンパイルし、C#コンパイラによって生成された「モデル」ツリーから/Tの間で型を書き換える可能性もあります(算術の優先順位を維持するなど)...本当に興味がある場合は、コードを投稿できますそのような解決策のために(私は1時間ほどかかります!). 実行時のパフォーマンスは遅くなります。doubledecimal

于 2012-04-24T16:03:14.483 に答える
2

使用できますIConvertible。ただし、必要なものによっては、パフォーマンスの違いが大きくなる可能性があります。を使用する方法と比較するとSingle、その差は 50% 近く大きくなる可能性があります。Generic を使用して 109ms と 156ms の単一テイクで 100000 回の反復を実行します。

このコードを参照してください (.Net 2):

using System;
using System.Text;
using NUnit.Framework;

namespace ProofOfConcept.GenericInterpolation
{
    /// <summary>
    /// Proof of concept for a generic Interpolate.
    /// </summary>
    [TestFixture]
    public class GenericInterpolationTest
    {
        /// <summary>
        /// Interpolate test.
        /// </summary>
        [Test]
        public void InterpolateTest()
        {
            Int16 interpolInt16 = Interpolate<Int16>(2, 4, 5, 6, 7);
            Int32 interpolInt32 = Interpolate<Int32>(2, 4, 5, 6, 7);

            Double interpolDouble = Interpolate<Double>(2, 4, 5, 6, 7);
            Decimal interpolDecimal = Interpolate<Decimal>(2, 4, 5, 6, 7);

            Assert.AreEqual((Int16)interpolInt32, (Int16)interpolInt16);
            Assert.AreEqual((Double)interpolDouble, (Double)interpolDecimal);

            //performance test
            int qtd = 100000;
            DateTime beginDt = DateTime.Now;
            TimeSpan totalTimeTS = TimeSpan.Zero;
            for (int i = 0; i < qtd; i++)
            {
                interpolDouble = Interpolate(2, 4, 5, 6, 7);
            }
            totalTimeTS = DateTime.Now.Subtract(beginDt);
            Console.WriteLine(
                "Non Generic Single, Total time (ms): " + 
                totalTimeTS.TotalMilliseconds);

            beginDt = DateTime.Now;
            for (int i = 0; i < qtd; i++)
            {
                interpolDouble = Interpolate<Double>(2, 4, 5, 6, 7);
            }
            totalTimeTS = DateTime.Now.Subtract(beginDt);
            Console.WriteLine(
                "Generic, Total time (ms): " + 
                totalTimeTS.TotalMilliseconds);
        }

        /// <summary>
        /// Interpolates the specified x1.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="x1">The x1.</param>
        /// <param name="y1">The y1.</param>
        /// <param name="x2">The x2.</param>
        /// <param name="y2">The y2.</param>
        /// <param name="x">The x.</param>
        /// <returns></returns>
        public static T Interpolate<T>(T x1, T y1, T x2, T y2, T x) where T : IConvertible
        {
            IConvertible x1C = x1 as IConvertible;
            IConvertible y1C = y1 as IConvertible;
            IConvertible x2C = x2 as IConvertible;
            IConvertible y2C = y2 as IConvertible;
            IConvertible xC = x as IConvertible;
            Decimal retDec = y1C.ToDecimal(null) + 
               (xC.ToDecimal(null) - x1C.ToDecimal(null)) * 
               (y2C.ToDecimal(null) - y1C.ToDecimal(null)) / 
               (x2C.ToDecimal(null) - x1C.ToDecimal(null));

            return (T)((IConvertible)retDec).ToType(typeof(T), null);
        }

        /// <summary>
        /// Interpolates the specified x1.
        /// </summary>
        /// <param name="x1">The x1.</param>
        /// <param name="y1">The y1.</param>
        /// <param name="x2">The x2.</param>
        /// <param name="y2">The y2.</param>
        /// <param name="x">The x.</param>
        /// <returns></returns>
        public static Single Interpolate(Single x1, Single y1, Single x2, Single y2, Single x)
        {
            Single retSing = y1 + (x - x1) * (y2 - y1) / (x2 - x1);

            return retSing;
        }
    }
}
于 2012-04-24T17:44:14.833 に答える