2011-01-12 13 views
33

TimeSpan.FromSeconds एक डबल लेता है, और 100 नैनोसेकंड तक मानों का प्रतिनिधित्व कर सकता है, हालांकि यह विधि पूरे मिलीसेकंड के समय को निष्पक्ष रूप से गोल करती है।TimeSpan.FromSeconds (डबल) मिलीसेकंड के लिए राउंड क्यों करता है?

यह देखते हुए कि मैंने इस (दस्तावेज!) व्यवहार को इंगित करने के लिए केवल आधे घंटे बिताए हैं, यह जानकर कि यह मामला क्यों बर्बाद समय के साथ आसान हो जाएगा।

क्या कोई सुझाव दे सकता है कि ऐसा प्रतीत होता है कि यह उत्पादक व्यवहार क्यों लागू किया गया है?

TimeSpan.FromSeconds(0.12345678).TotalSeconds 
    // 0.123 
TimeSpan.FromTicks((long)(TimeSpan.TicksPerSecond * 0.12345678)).TotalSeconds 
    // 0.1234567 
+0

मुझे पुराना जवाब देखने के लिए खेद है। मुझे संदेह है कि मैं कुछ भी बेहतर तरीके से आ सकता हूं (और मैं इसे +1 करना चाहता था ...) – Peter

+0

"[के] अब यह क्यों हो सकता है कि यह मामला बर्बाद समय के साथ आसान हो जाएगा।" इसे एक सनकी लागत पर विचार करें। – jason

+1

उस भी काट दिया गया। मेरा सिद्धांत यह है कि यह .NET 1 में एक बग था और इसे बदला नहीं गया है क्योंकि यह मौजूदा प्रोग्राम तोड़ देगा। आईएमओ एमएस को यह इंगित करने के लिए इंटेलिजेंस विवरण को कम से कम अद्यतन करना चाहिए कि इन फ़ंक्शन में केवल मिलीसेकंड सटीक है। – CodesInChaos

उत्तर

11

जैसा कि आपने स्वयं को पाया है, यह एक दस्तावेजी विशेषता है। यह documentation of TimeSpan में वर्णित है:

पैरामीटर

मूल्य प्रकार: प्रणाली।डबल

कई सेकंड, निकटतम मिलीसेकंद के लिए सटीक।

इसका कारण शायद इसलिए है क्योंकि एक डबल बिल्कुल सटीक नहीं है। युगल की तुलना करते समय कुछ गोल करने के लिए हमेशा अच्छा विचार होता है, क्योंकि यह अपेक्षाकृत अपेक्षाकृत छोटा या छोटा हो सकता है। जब आप पूरे मिलीसेकंड में डालने का प्रयास करते हैं तो वह व्यवहार वास्तव में आपको कुछ अप्रत्याशित नैनोसेकंड प्रदान कर सकता है। मुझे लगता है कि यही कारण है कि उन्होंने मूल्य को पूरे मिलीसेकंड में गोल करने के लिए चुना और छोटे अंकों को त्याग दिया।

+0

"अप्रत्याशित नैनोसेकंड" एक व्यावहारिक सिद्धांत की तरह लगता है। अभी भी _my_ पुस्तक में इसे उचित नहीं ठहराता है, लेकिन यह बिंदु के बगल में है। +1। –

+0

हां, लेकिन अधिकांश लोगों के लिए मिलीसेकंड शायद पर्याप्त होंगे। जो लोग नैनोसेकंड के साथ काम करने के लिए पर्याप्त स्मार्ट हैं, वे 'टाइमस्पेन.फ्रॉमटिक्स (टाइमस्पेन। टिकर्स सेकेंड * आपका सेकेंड डबल) का उपयोग कर सकते हैं। ;) – GolezTrol

0

FromSeconds नहीं हो रहा है निजी विधि अंतराल

public static TimeSpan FromSeconds(double value) 
{ 
    return Interval(value, 0x3e8); 
} 

का उपयोग करता है 0x3e8 == 1000

अंतराल विधि multiplay कि स्थिरांक पर मूल्य और फिर लंबे समय तक के लिए डाली (अंतिम पंक्ति देखें):

private static TimeSpan Interval(double value, int scale) 
{ 
    if (double.IsNaN(value)) 
    { 
     throw new ArgumentException(Environment.GetResourceString("Arg_CannotBeNaN")); 
    } 
    double num = value * scale; // Multiply!!!! 
    double num2 = num + ((value >= 0.0) ? 0.5 : -0.5); 
    if ((num2 > 922337203685477) || (num2 < -922337203685477)) 
    { 
     throw new OverflowException(Environment.GetResourceString("Overflow_TimeSpanTooLong")); 
    } 
    return new TimeSpan(((long) num2) * 0x2710L); // Cast to long!!! 
} 

परिणाम के रूप में हम 3 (x1000) संकेत के साथ सटीक है। उपयोग परावर्तक

+0

मैंने निश्चित रूप से देखा। परावर्तक हमेशा _how_ का उत्तर दे सकता है, लेकिन _why_ नहीं। क्या यह आपको यह जानने में मदद करता है कि क्यों कास्ट लंबे समय तक ** ** गुणा से पहले होता है?मैं मानता हूं कि एक बग को दस्तावेज नहीं किया गया था। शायद यह अभी भी एक बग था जो ठीक करने के लिए दस्तावेज़ से आसान था। निचली पंक्ति यह है कि, यह कोड "क्यों" प्रश्न का उत्तर नहीं देता है। –

+1

@romkyns "ठीक करने के लिए दस्तावेज़ के लिए एक बग आसान है!" मुझे लगता है कि आपने अभी माइक्रोसॉफ्ट के नए नारे को पाया है! ;-) –

+0

@ निकोलस: एक अलग वाक्यांश के रूप में यह मनोरंजक लगता है। लेकिन मुझे नहीं लगता कि हमारे पास _unexpected_ बग है। यह डिजाइन जानबूझकर हो सकता है। –

7

एक अटकलों का अधिकार पर ..

  1. TimeSpan.MaxValue.TotalMilliseconds है equat 922337203685477. को संख्या 15 अंक है कि जांच करने के लिए।
  2. double 15 अंकों के लिए सटीक है।
  3. TimeSpan.FromSeconds, TimeSpan.FromMinutes आदि सब (तब TimeSpan तो टिक करने के लिए जो अब दिलचस्प नहीं है) double में व्यक्त मिलीसेकेंड के लिए रूपांतरण के माध्यम से जाने

इसलिए, जब आप TimeSpan पैदा कर रहे है कि TimeSpan.MaxValue के करीब होगा (या MinValue) रूपांतरण केवल मिलीसेकंड पर सटीक होगा।
तो सवाल करने के लिए संभावित जवाब "क्यों" है: ही परिशुद्धता हर समय है।
इस बारे में सोचने के लिए और बात यह है कि अगर long में व्यक्त की गई टिकों के लिए रूपांतरणों को पहले परिवर्तित करने के माध्यम से रूपांतरण किया गया था तो यह काम बेहतर हो सकता था।

+0

दस्तावेज़ों के मुताबिक, मूल्य * पहले * टिकों में परिवर्तित हो गया है। – GolezTrol

+0

@ गोलेज़: आप इस दस्तावेज़ को कहां देखते थे? [Value पैरामीटर मिलीसेकेंड में बदल जाती है, जो टिक में बदल जाती है, और टिक की संख्या नई TimeSpan intialize करने के लिए प्रयोग किया जाता है] (http://msdn.microsoft.com/en-us/library/system.timespan.fromseconds .aspx) –

+0

मुझे खेद है, मैं गलत पढ़ता हूं। – GolezTrol

4

कल्पना कीजिए कि आप TimeSpan प्रकार को डिज़ाइन करने के लिए जिम्मेदार डेवलपर हैं। आपके पास जगह की सभी बुनियादी कार्यक्षमताएं हैं; यह सब महान काम कर रहा प्रतीत होता है। फिर एक दिन कुछ बीटा परीक्षक साथ आता है और आप इस कोड को दिखाता है:

double x = 100000000000000; 
double y = 0.5; 
TimeSpan t1 = TimeSpan.FromMilliseconds(x + y); 
TimeSpan t2 = TimeSpan.FromMilliseconds(x) + TimeSpan.FromMilliseconds(y); 
Console.WriteLine(t1 == t2); 

क्यों कि उत्पादन False? परीक्षक आपको पूछता है। भले ही आप समझते हैं कि ऐसा क्यों हुआ (x और y को जोड़ने में परिशुद्धता का नुकसान), आपको यह मानना ​​है कि क्लाइंट परिप्रेक्ष्य से थोड़ा अजीब लगता है।

x = 10.0; 
y = 0.5; 
t1 = TimeSpan.FromMilliseconds(x + y); 
t2 = TimeSpan.FromMilliseconds(x) + TimeSpan.FromMilliseconds(y); 
Console.WriteLine(t1 == t2); 

यह एक आउटपुट True: तो फिर वह आप पर इस एक फेंकता है! परीक्षक समझदारी से संदेहजनक है।

इस बिंदु पर आपके पास निर्णय लेने का निर्णय है। या तो आप TimeSpan मूल्यों के बीच अंकगणितीय संचालन कि double मूल्यों से निर्माण किया गया एक परिणाम जिसका सटीक double प्रकार ही -eg, 100,000,000,000,000.5 (16 महत्वपूर्ण आंकड़े) की सटीकता से अधिक उपज के लिए अनुमति दे सकते हैं -या आप कर सकते हैं, तो आप पता है, इसे अनुमति दें।

तो आप तय करते हैं, आप जानते हैं कि, मैं सिर्फ यह इतना है कि बनाती हूँ कोई भी तरीका एक double का उपयोग करता है के निर्माण के लिए एक TimeSpan निकटतम मिलीसेकंड के लिए बढ़ा दिया जाएगा। इस तरह, यह स्पष्ट रूप से दस्तावेज किया गया है जो double से TimeSpan में कनवर्ट करना एक हानिकारक ऑपरेशन है, जो मुझे ऐसे मामलों में पूर्ण करता है जहां ग्राहक double से TimeSpan में परिवर्तित होने और सटीक परिणाम की उम्मीद करने के बाद इस तरह अजीब व्यवहार देखता है।

मैं जरूरी नहीं कि यह तर्कसंगत है कि यह "सही" निर्णय है; स्पष्ट रूप से, यह दृष्टिकोण अपने आप पर कुछ भ्रम पैदा करता है। मैं बस इतना कह रहा हूं कि एक निर्णय या एक दूसरे के लिए एक निर्णय की जरूरत है, और यह स्पष्ट रूप से तय किया गया था।

+0

आप यह बहुत ही तर्क इस्तेमाल कर सकते हैं पूरी तरह गैर-कानूनी घोषित युगल करने के लिए ... लेकिन फिर भी, मैं डिजाइनरों निरपेक्ष शुरुआती के लिए अनुचित ध्यान दे इस विशिष्ट वर्ग का परीक्षण करते हुए कल्पना कर सकते हैं ... काश यह कैसे अस्तित्व में आया हम निश्चित रूप से पता कर सकते हैं:) –

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