प्रश्न पर अच्छी तरह से चर्चा की गई है, लेकिन चूंकि मैं थोड़ी देर के लिए इस समस्या को खो रहा था, इसलिए मैं अपने कुछ परिणामों को साझा करना चाहता हूं।
समस्या परिभाषा: दशमलव युगल तुलना में बहुत धीमी होने के लिए जाना जाता है लेकिन वित्तीय अनुप्रयोगों किसी भी कलाकृतियों कि पैदा होती है जब गणना युगल पर प्रदर्शन कर रहे हैं बर्दाश्त नहीं कर सकते।
रिसर्च
मेरा उद्देश्य नाव की दिशा वाला संख्या के भंडारण के विभिन्न दृष्टिकोणों को मापने के लिए और एक निष्कर्ष जो एक हमारे आवेदन के लिए इस्तेमाल किया जाना चाहिए बनाने के लिए किया गया था।
अगर हमारे लिए Int64
का उपयोग निश्चित परिशुद्धता के साथ फ़्लोटिंग पॉइंट नंबरों को स्टोर करने के लिए स्वीकार्य था। 10^6 का गुणक हमें दोनों दे रहा था: बड़ी संख्या में स्टोर करने के लिए भिन्न संख्याओं को भरने और बड़ी मात्रा में स्टोर करने के लिए पर्याप्त अंक। बेशक, आपको इस दृष्टिकोण के साथ सावधान रहना होगा (गुणा और विभाजन संचालन मुश्किल हो सकता है), लेकिन हम तैयार थे और इस दृष्टिकोण को मापना चाहते थे। संभावित गणना त्रुटियों और अतिप्रवाहों को छोड़कर आपको एक बात ध्यान में रखना है, आमतौर पर आप उन लंबी संख्याओं को सार्वजनिक एपीआई में बेनकाब नहीं कर सकते हैं। तो सभी आंतरिक गणना लंबे समय से की जा सकती है लेकिन उपयोगकर्ता को संख्या भेजने से पहले उन्हें कुछ और दोस्ताना रूपांतरित कर दिया जाना चाहिए।
मैंने एक साधारण प्रोटोटाइप वर्ग लागू किया है जो दशमलव-जैसी संरचना के लिए एक लंबा मूल्य लपेटता है (इसे Money
कहा जाता है) और इसे माप में जोड़ा गया।
public struct Money : IComparable
{
private readonly long _value;
public const long Multiplier = 1000000;
private const decimal ReverseMultiplier = 0.000001m;
public Money(long value)
{
_value = value;
}
public static explicit operator Money(decimal d)
{
return new Money(Decimal.ToInt64(d * Multiplier));
}
public static implicit operator decimal (Money m)
{
return m._value * ReverseMultiplier;
}
public static explicit operator Money(double d)
{
return new Money(Convert.ToInt64(d * Multiplier));
}
public static explicit operator double (Money m)
{
return Convert.ToDouble(m._value * ReverseMultiplier);
}
public static bool operator ==(Money m1, Money m2)
{
return m1._value == m2._value;
}
public static bool operator !=(Money m1, Money m2)
{
return m1._value != m2._value;
}
public static Money operator +(Money d1, Money d2)
{
return new Money(d1._value + d2._value);
}
public static Money operator -(Money d1, Money d2)
{
return new Money(d1._value - d2._value);
}
public static Money operator *(Money d1, Money d2)
{
return new Money(d1._value * d2._value/Multiplier);
}
public static Money operator /(Money d1, Money d2)
{
return new Money(d1._value/d2._value * Multiplier);
}
public static bool operator <(Money d1, Money d2)
{
return d1._value < d2._value;
}
public static bool operator <=(Money d1, Money d2)
{
return d1._value <= d2._value;
}
public static bool operator >(Money d1, Money d2)
{
return d1._value > d2._value;
}
public static bool operator >=(Money d1, Money d2)
{
return d1._value >= d2._value;
}
public override bool Equals(object o)
{
if (!(o is Money))
return false;
return this == (Money)o;
}
public override int GetHashCode()
{
return _value.GetHashCode();
}
public int CompareTo(object obj)
{
if (obj == null)
return 1;
if (!(obj is Money))
throw new ArgumentException("Cannot compare money.");
Money other = (Money)obj;
return _value.CompareTo(other._value);
}
public override string ToString()
{
return ((decimal) this).ToString(CultureInfo.InvariantCulture);
}
}
प्रयोग
मैं संचालन निम्नलिखित मापा: इसके अलावा, घटाव, गुणा, विभाजन, समानता तुलना और रिश्तेदार (अधिक से अधिक/कम) तुलना। मैं निम्नलिखित प्रकारों पर परिचालन को माप रहा था: double
, long
, decimal
और Money
। प्रत्येक ऑपरेशन 1.000.000 बार किया गया था। सभी संख्याओं को सरणी में पूर्व-आवंटित किया गया था, इसलिए decimal
और Money
के रचनाकारों में कस्टम कोड को कॉल करना परिणाम को प्रभावित नहीं करना चाहिए।
Added moneys in 5.445 ms
Added decimals in 26.23 ms
Added doubles in 2.3925 ms
Added longs in 1.6494 ms
Subtracted moneys in 5.6425 ms
Subtracted decimals in 31.5431 ms
Subtracted doubles in 1.7022 ms
Subtracted longs in 1.7008 ms
Multiplied moneys in 20.4474 ms
Multiplied decimals in 24.9457 ms
Multiplied doubles in 1.6997 ms
Multiplied longs in 1.699 ms
Divided moneys in 15.2841 ms
Divided decimals in 229.7391 ms
Divided doubles in 7.2264 ms
Divided longs in 8.6903 ms
Equility compared moneys in 5.3652 ms
Equility compared decimals in 29.003 ms
Equility compared doubles in 1.727 ms
Equility compared longs in 1.7547 ms
Relationally compared moneys in 9.0285 ms
Relationally compared decimals in 29.2716 ms
Relationally compared doubles in 1.7186 ms
Relationally compared longs in 1.7321 ms
निष्कर्ष
- अलावा, घटाव, गुणा,
decimal
पर तुलना संचालन long
या double
पर कार्रवाई की तुलना में ~ 15 गुना धीमी कर रहे हैं; विभाजन ~ 30 गुना धीमा है।
Decimal
का प्रदर्शन Decimal
के प्रदर्शन से बेहतर है लेकिन सीएलआर से समर्थन की कमी के कारण double
और long
के प्रदर्शन से काफी खराब है।
- पूर्ण संख्या में
Decimal
पर गणना करना काफी तेज है: प्रति सेकंड 40.000.000 संचालन।
सलाह
- जब तक आप एक बहुत भारी गणना मामला है, दशमलव का उपयोग करें। सापेक्ष संख्या में वे लंबे और युगल से धीमे होते हैं, लेकिन पूर्ण संख्या अच्छी लगती है।
- सीएलआर से समर्थन के उत्थान के कारण
Decimal
को अपनी खुद की संरचना के साथ फिर से कार्यान्वित करने में बहुत कुछ नहीं है। आप इसे Decimal
से तेज़ी से बना सकते हैं लेकिन यह double
जितना तेज़ नहीं होगा।
- यदि
Decimal
का प्रदर्शन आपके आवेदन के लिए पर्याप्त नहीं है, तो आप निश्चित गणना के साथ अपनी गणना long
पर स्विच करने पर विचार करना चाहेंगे। परिणाम को ग्राहक को वापस करने से पहले इसे Decimal
में परिवर्तित किया जाना चाहिए।
आप समयपूर्व अनुकूलन के कगार पर हैं, बस ऐप को सही तरीके से कोड करें, फिर – TravisO
तथ्य के बाद ट्विक करें आपने सभी निम्न स्तर सी # अनुकूलन किए हैं। कुछ एल्गोरिदमिक सुधार शेष हो सकते हैं (उदाहरण के लिए दशमलव पर कम परिचालन करना)। – Brian
एक समय-संवेदनशील वित्तीय अनुप्रयोग में डेटाबेस संचालन खराब लगता है ... –