2012-04-24 9 views
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 ऑपरेटर '' प्रकार के ऑपरेंड 'टी' और 'टी' सी करने के लिए लागू नहीं किया जा सकता: \ Git ... \ LinearInterpolator.cs

मुझे अपना कोड पुन: उपयोग कैसे करना चाहिए?

संपादित करें: इस मॉड्यूल के लिए तेज़ रनटाइम महत्वपूर्ण है।

+3

सुंदर यकीन है कि आप और अधिक कर रहे हैं या उससे कम क्या तुम वहाँ के साथ अटक ... – Servy

+1

'System.Double' और' System.Decimal' के रूप में आपको आवश्यक ऑपरेटरों को परिभाषित करने वाले एक सामान्य पूर्वजों को साझा न करें, मुझे डर है कि आप नहीं कर सकते हैं। –

+0

सी # शब्द की सामान्य समझ में "जेनेरिक" नहीं है। टी से कुछ भी उपयोग करना संभव नहीं है, जब तक कि इसका प्रकार पहले से ज्ञात नहीं है (बाध्य)। –

उत्तर

3

आप T पर बेस क्लास बाधा निर्दिष्ट किए बिना जेनेरिक में ऑपरेटरों का उपयोग नहीं कर सकते हैं।

आप ऐसा कुछ कर सकते हैं: Creating a Math library using Generics in C# लेकिन व्यक्तिगत रूप से, जब तक कि आपके पास वास्तव में बहुत सारे सूत्र नहीं हैं तब मुझे बहुत अधिक बिंदु नहीं दिखता है।

वहाँ भी गतिशील T के लिए अभिव्यक्ति के पेड़ संकलन, सी # संकलक द्वारा उत्पन्न एक 'मॉडल' पेड़ से double/decimal के बीच प्रकार पुनर्लेखन (गणित पूर्वता आदि रखने के लिए) की संभावना है ... अगर आप वास्तव में कर रहे हैं इसमें दिलचस्पी है कि मैं इस तरह के समाधान के लिए कोड पोस्ट कर सकता हूं (मुझे एक घंटे या फिर भी आवश्यकता होगी!)। रनटाइम प्रदर्शन धीमा हो जाएगा।

+0

निराशाजनक के लिए धन्यवाद। मुझे धीमी गति से दिलचस्पी नहीं है, मैं अपने डुप्लिकेशंस के साथ रहना चाहता हूं। –

+0

मुझे नहीं पता कि एक गतिशील रूप से संकलित संस्करण "धीमा" होगा, वर्तमान अधिभार की तुलना में थोड़ा धीमा। मैं उम्मीद करता हूं कि यह मेरे 'गतिशील' संस्करण से तुलनीय हो। – Gabe

+0

@Gabe आप शायद सही हैं (और मैं व्यक्तिगत रूप से गतिशील रूप से संकलित और गतिशील 'सामान में बहुत सारे स्टॉक रखता हूं, मुझे लगता है कि कम से कम प्रारंभिक गर्म होने के बाद, अक्सर मुझे लगता है कि प्रदर्शन मेरी उम्मीदों से अधिक है) - मैं इसे इसके खिलाफ बेंचमार्क कर सकता हूं यदि मैं समय का एक मुफ्त टुकड़ा मिलता हूं तो आपका गतिशील समाधान। देखना वास्तव में दिलचस्प होगा :) –

4

आपका वर्तमान कोड ठीक है जैसा कि संभव है - संभवतः आप सबसे अच्छा सर्वश्रेष्ठ प्राप्त कर सकते हैं जो कि डबल्स को दशमलव के बिना हासिल कर सकते हैं।

एक सामान्य समाधान संभव है, लेकिन इसमें बहुत सारे बुनियादी ढांचे शामिल होंगे - इतना है कि इससे चीजें बहुत जटिल हो जाएंगी।

+0

+1 मैं जटिलता से बचने के लिए सभी हूं। –

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); 
} 
+1

+1 दिलचस्प दृष्टिकोण! –

2

आप IConvertible का उपयोग कर सकते हैं। लेकिन प्रदर्शन की आवश्यकता आपके लिए आवश्यकतानुसार काफी हो सकती है। Single का उपयोग करने वाली विधि के मुकाबले, अंतर लगभग 50% अधिक हो सकता है। 100000 पुनरावृत्तियों को करने के साथ, जेनेरिक का उपयोग करके एकल 109ms और 156ms लेता है।

इस कोड (नेट 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; 
     } 
    } 
} 
+0

+1 कुछ बहुत ही रोचक बेंचमार्किंग! –

संबंधित मुद्दे