Double.TryParse या Convert.ToDouble - जो तेज और सुरक्षित है?


80

मेरा एप्लिकेशन VSTO का उपयोग करके एक एक्सेल फाइल पढ़ता है और रीड डेटा को एक में जोड़ता है StringDictionary। यह केवल डेटा जोड़ता है जो कुछ अंकों (1000 1000,2 1000,34 - कॉमा रूसी मानकों में एक सीमांकक) के साथ संख्याएं हैं।

यदि वर्तमान स्ट्रिंग एक उपयुक्त संख्या है, तो जांचना बेहतर है?

object data, string key; // data had read

try
{
  Convert.ToDouble(regionData, CultureInfo.CurrentCulture);
  dic.Add(key, regionData.ToString());
}
catch (InvalidCastException)
{
  // is not a number
}

या

double d;
string str = data.ToString();
if (Double.TryParse(str, out d)) // if done, then is a number
{
  dic.Add(key, str);
}

मुझे निम्नलिखित पार्सिंग एल्गोरिदम मुद्दों StringDictionaryके Dictionary<string, double>कारण उपयोग करना होगा ।

मेरे सवाल: कौन सा तरीका तेज है? कौन सा ज्यादा सुरक्षित है?

और क्या यह कॉल करना बेहतर है Convert.ToDouble(object)या Convert.ToDouble(string)?


FYI करें, double.TryParse एक ही चीज़ है जैसा कि कोशिश {परिणाम = double.Parse (s); सच लौटना; } {झूठा पकड़ना; }। कन्वर्ट अनिवार्य रूप से ओवरलोड के एक गुच्छा के साथ दोनों के लिए एक आवरण है। इससे कोई फर्क नहीं पड़ता कि आप इसे कैसे करते हैं। लेकिन जैसा कि जॉन ने बताया है, खराब इनपुट को संभालने के तरीके के बारे में सोचें।
जॉन Leidegren

12
Double.TryParse डबल के रूप में ही नहीं है। एक कोशिश में लिपटे। शब्दार्थ समान हैं, लेकिन कोड पथ अलग है। TryParse पहले पुष्टि करता है कि स्ट्रिंग एक आंतरिक संख्या का उपयोग कर एक संख्या है। TryStringToNumber, जबकि Parse मानती है कि यह पहले से ही एक संख्या / डबल है।
जेफ मोजर

जवाबों:


131

मैंने रिलीज़ मोड में एक त्वरित गैर-वैज्ञानिक परीक्षण किया। मैंने दो इनपुट का उपयोग किया: "2.34523" और "बैडिनपुट" दोनों विधियों में और 1,000,000 बार पुनरावृत्त।

मान्य इनपुट:

Double.TryParse = 646ms
Convert.ToDouble = 662 ms

उम्मीद के मुताबिक ज्यादा अलग नहीं। सभी इनपुट और उद्देश्यों के लिए, मान्य इनपुट के लिए, ये समान हैं।

अमान्य निवेश:

Double.TryParse = 612ms
Convert.ToDouble = ..

खैर .. बहुत दिनों से चल रहा था। मैंने 1,000 पुनरावृत्तियों का उपयोग करके पूरी चीज़ को फिर से चलाया और Convert.ToDoubleखराब इनपुट के साथ 8.3 सेकंड का समय लिया। इसका लाभ उठाते हुए, इसमें 2 घंटे का समय लगेगा। मुझे परवाह नहीं है कि अमान्य इनपुट मामले में परीक्षण कितना बुनियादी है, Convert.ToDoubleइसका अपवाद उठाना आपके प्रदर्शन को बर्बाद कर देगा।

इसलिए, यहां TryParseकुछ अन्य वोटों के साथ इसे वापस करने के लिए एक और वोट दिया गया है।


4
उपर्युक्त बातों के अलावा, मैंने अभी पाया कि Convert.ToDouble () वैज्ञानिक संकेतन में संख्याओं के साथ एक अपवाद फेंक देगा। इस पर विचार करें: डबल toDouble = Convert.ToDouble ((- 1/30000) .ToString ()); // डबल dblParse को विफल करेगा = Double.Parse ((- 1/30000) .ToString ()); // ठीक काम करता है
बडी ली

46

के साथ शुरू करने के लिए, मैं पहली जगह के double.Parseबजाय का उपयोग करेंगे Convert.ToDouble

जैसे कि आपको उपयोग करना चाहिए Parseया क्या आप TryParseआगे बढ़ सकते हैं यदि खराब इनपुट डेटा है, या क्या यह वास्तव में असाधारण स्थिति है? यदि यह असाधारण है, तो उपयोग करें Parseऔर यदि इनपुट खराब है, तो इसे उड़ा दें। यदि यह अपेक्षित है और इसे आसानी से संभाला जा सकता है, तो उपयोग करें TryParse


6
जॉन, क्या आप इस बारे में विस्तार से बता सकते हैं कि आप Convert.ToDouble पर डबल भुगतान क्यों पसंद करते हैं?
डेविड नॉर्थ

10
@dnorthut: मैं शायद ही कभी शून्य को 0 में परिवर्तित करना चाहता हूं (जो Convert.ToDouble करता है), मूल रूप से। यह भी आम तौर पर अधिक लचीला है। मैं केवल विशिष्ट विधियों के लिए जाना चाहता हूँ ...
जॉन स्कीट

8

.NET फ्रेमवर्क डिज़ाइन दिशानिर्देश, ट्राई विधियों का उपयोग करने की सलाह देते हैं। अपवादों से बचना आमतौर पर एक अच्छा विचार है।

Convert.ToDouble(object) करूँगा ((IConvertible) object).ToDouble(null);

जो बुलाएगा Convert.ToDouble(string, null)

तो यह स्ट्रिंग संस्करण को कॉल करने के लिए तेज़ है।

हालाँकि, स्ट्रिंग संस्करण बस यही करता है:

if (value == null)
{
    return 0.0;
}
return double.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);

तो यह double.Parseसीधे करने के लिए तेजी से है ।


7

यदि आप अपवाद को संभालने नहीं जा रहे हैं तो TryParse के साथ जाएं। TryParse तेज है क्योंकि इसे पूरे अपवाद स्टैक ट्रेस से निपटने की आवश्यकता नहीं है।


7

मैं आम तौर पर Convertवर्ग से बचने की कोशिश करता हूं (मतलब: मैं इसका उपयोग नहीं करता) क्योंकि मुझे यह बहुत भ्रामक लगता है: कोड बहुत कम संकेत देता है कि यहां वास्तव में क्या होता है क्योंकि Convertएक ही कोड के साथ बहुत अधिक अलग-अलग रूपांतरण होने की अनुमति देता है । इससे प्रोग्रामर के लिए नियंत्रित करना कठिन हो जाता है कि वास्तव में क्या हो रहा है।

मेरी सलाह, इसलिए इस वर्ग का उपयोग कभी नहीं करना चाहिए। यह वास्तव में आवश्यक नहीं है (एक संख्या के द्विआधारी स्वरूप को छोड़कर, क्योंकि ToStringसंख्या वर्गों की सामान्य विधि ऐसा करने के लिए एक उपयुक्त विधि प्रदान नहीं करती है)।


7

जब तक आप अपने इनपुट के 100% निश्चित नहीं हैं, जो कि शायद ही कभी होता है, तो आपको Double.TryParse का उपयोग करना चाहिए।

Convert.ToDouble will throw an exception on non-numbers
Double.Parse will throw an exception on non-numbers or null
Double.TryParse will return false or 0 on any of the above without generating an exception.

जब आप अपवाद को छोड़ते हैं, तो अपवाद को फेंकने की गति धीमी हो जाती है, क्योंकि आप अपवाद छोड़ देते हैं।


4

यहाँ धर्मान्तरित वर्ग के लिए बहुत घृणा ... बस थोड़ा सा संतुलन करने के लिए, धर्मान्तरण का एक फायदा है - यदि आपको कोई वस्तु सौंपी जाती है,

Convert.ToDouble(o);

यदि ओ पहले से ही एक डबल (या एक इंट या कुछ आसानी से कास्टेबल) है तो आसानी से मूल्य वापस कर सकते हैं।

यदि आप पहले से ही एक स्ट्रिंग में है, लेकिन Double.Parse या Double.TryParse का उपयोग करना बहुत अच्छा है

Double.Parse(o.ToString());

पहले स्ट्रिंग को पार करने के लिए जाना पड़ता है और आपके इनपुट के आधार पर यह अधिक महंगा हो सकता है।


1
+1: मैं आपकी बात देखता हूं, एक बड़े पैमाने पर जाँच के बजाय एक System.Object के अंदर नंबर के साथ बॉक्सिंग नंबर / स्ट्रिंग्स को पार्स करना बहुत आसान है। लेकिन मूल रूप से मैं अन्य उत्तरों से सहमत हूं: Convert.ToSomething()पार्से / ट्रायपार्से के बजाय बहुत महंगा है, विशेष रूप से एक पुनरावृत्ति संदर्भ में
T-moty

मेरे लिए, Convert.ToDouble (ओ) कुछ आसान बाहरी है अगर बॉक्स में पहले से ही एक नंबर है, लेकिन कन्वर्ट के लिए असली हत्यारा यह है कि यह एक .TryToDouble (ओ, आउट डी) नहीं है; यह देखते हुए कि कितने महंगे अपवाद हैं (और आप कितने आश्वस्त हैं - या नहीं - इनपुट्स के), यह कन्वर्ट का बड़ा अतिरिक्त खर्च है।
user1664043

2

डबल.ट्रीपर्स आईएमओ।

आपके लिए संभालना आसान है, आपको पता चल जाएगा कि त्रुटि कहां हुई थी।

फिर आप इससे निपट सकते हैं कि कैसे आप फिट दिखें अगर यह गलत है (यानी परिवर्तित नहीं हो सकता)।


2

मैंने हमेशा TryParse()विधियों का उपयोग करना पसंद किया है क्योंकि यह अपवादों की चिंता किए बिना सफलता या विफलता को वापस करने के लिए थूकने वाला है।


2

यह एक दिलचस्प पुराना सवाल है। मैं एक उत्तर जोड़ रहा हूं क्योंकि मूल प्रश्न के साथ किसी ने कुछ भी नहीं देखा।

कौन सा तेज़ है: Convert.ToDouble या Double.TryParse? कौन सा अधिक सुरक्षित है: Convert.ToDouble या Double.TryParse?

मैं इन दोनों सवालों का जवाब देने जा रहा हूं (मैं बाद में जवाब अपडेट करूंगा), विस्तार से, लेकिन पहले:

सुरक्षा के लिए, इस प्रश्न में प्रत्येक प्रोग्रामर से चूकने वाली बात लाइन (जोर मेरा) है:

यह केवल डेटा जोड़ता है जो कुछ अंकों (1000 1000,2 1000,34 - कॉमा रूसी मानकों में एक सीमांकक ) के साथ संख्याएं हैं ।

इस कोड उदाहरण द्वारा अनुसरण किया गया:

Convert.ToDouble(regionData, CultureInfo.CurrentCulture);

यहां यह दिलचस्प है कि यदि स्प्रेडशीट रूसी संख्या प्रारूप में है, लेकिन एक्सेल ने सेल फ़ील्ड को सही ढंग से टाइप नहीं किया है, तो एक्सेल से आने वाले मानों की सही व्याख्या क्या है?

यहाँ दो उदाहरणों के बारे में एक और दिलचस्प बात है, गति के बारे में:

catch (InvalidCastException)
{
    // is not a number
}

यह MSIL उत्पन्न करने की संभावना है जो इस तरह दिखता है:

catch [mscorlib]System.InvalidCastException 
{
  IL_0023:  stloc.0
  IL_0024:  nop
  IL_0025:  ldloc.0
  IL_0026:  nop
  IL_002b:  nop
  IL_002c:  nop
  IL_002d:  leave.s    IL_002f
}  // end handler
IL_002f: nop
IL_0030: return

इस अर्थ में, हम संभवतः प्रत्येक कार्यक्रम द्वारा किए गए MSIL निर्देशों की कुल संख्या की तुलना कर सकते हैं - इस पर बाद में जैसा कि मैंने इस पोस्ट को अपडेट किया है।

मेरा मानना ​​है कि कोड सही, स्पष्ट और तेज़ होना चाहिए ... उस क्रम में!


1

व्यक्तिगत रूप से, मुझे TryParseपढ़ने की विधि आसान लगती TryParseहै , जिसे आप वास्तव में उपयोग करना चाहते हैं वह आपके उपयोग-मामले पर निर्भर करता है: यदि त्रुटियों को स्थानीय रूप से नियंत्रित किया जा सकता है, तो आप त्रुटियों की उम्मीद कर रहे हैं और एक बूल अच्छा है, अन्यथा आप बस इसे जाने देना चाहते हैं अपवाद उड़ते हैं।

मुझे इसके TryParseतेजी से होने की भी उम्मीद है, क्योंकि यह अपवाद से निपटने के ओवरहेड से बचा जाता है। लेकिन विभिन्न संभावनाओं की तुलना करने के लिए जॉन स्कीट मिनीबेंच जैसे बेंचमार्क टूल का उपयोग करें।


इस उत्तर पर प्रतिक्रिया: यदि प्रश्न पूछते हैं कि क्या तेज और सुरक्षित है, तो जवाब के साथ शुरू नहीं होना चाहिए: "व्यक्तिगत रूप से" और इसमें अनुमान लगाना शामिल है: "मुझे उम्मीद है ..."। यह सिर्फ व्यक्तिगत विचार और टिप्पणी है, एक अच्छा जवाब नहीं है।
पांडवूड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.