क्या इसमें कोई फ़ंक्शन नैनोसेकंड को में एक std :: स्ट्रिंग में परिवर्तित करेगा, "3m12s" जैसा कुछ कहें?
सं।लेकिन मैं आपको दिखाऊंगा कि आप इसे आसानी से कैसे कर सकते हैं।
मैं std :: chrono :: steady_clock :: उपयोग करना चाहिए अब() हर बार मैं मेरी प्रगति बार अपडेट करते हैं और घटाना है कि TIME_LEFT निर्धारित करने के लिए _begin से?
हां।
वहाँ TIME_LEFT
निर्धारित करने के लिए एक बेहतर एल्गोरिथ्म है हां। निचे देखो।
संपादित
मैं मूल रूप से "के रूप में टिक" की गलत व्याख्या की थी "घड़ी टिक्स", वास्तविकता में जब "टिक्स" काम की इकाइयां हैं और _ticks_occurred/_total_ticks
% job_done रूप में व्याख्या की जा सकती है। तो मैंने तदनुसार प्रस्तावित progress_bar
बदल दिया है।
मेरा मानना है कि समीकरण:
time_left = (time_taken/_total_ticks) * (_total_ticks - _ticks_occured)
सही नहीं है। यह एक सैनिटी चेक पास नहीं करता है: यदि _ticks_occured == 1
और _total_ticks
बड़ा है, तो time_left
लगभग बराबर (ठीक है, थोड़ा कम) time_taken
। यह समझ में नहीं आता है।
मैं उपरोक्त समीकरण को फिर से लिखने रहा हो:
time_left = time_taken * (1/percent_done - 1)
जहां
percent_done = _ticks_occurred/_total_ticks
अब percent_done
के रूप में शून्य दृष्टिकोण, time_left
अनंत दृष्टिकोण है, और जब percent_done
दृष्टिकोण 1, 'time_left
दृष्टिकोण 0. जब percent_done
10% है, time_left
9*time_taken
है। यह मेरी अपेक्षाओं को पूरा करता है, प्रति कार्य-टिक के लिए मोटे तौर पर रैखिक समय लागत को मानता है।
class progress_bar
{
public:
progress_bar(uint64_t ticks)
: _total_ticks(ticks), _ticks_occurred(0),
_begin(std::chrono::steady_clock::now())
// ...
{}
void tick()
{
using namespace std::chrono;
// test to see if enough progress has elapsed
// to warrant updating the progress bar
// that way we aren't wasting resources printing
// something that hasn't changed
if (/* should we update */)
{
// somehow _ticks_occurred is updated here and is not zero
duration time_taken = Clock::now() - _begin;
float percent_done = (float)_ticks_occurred/_total_ticks;
duration time_left = time_taken * static_cast<rep>(1/percent_done - 1);
minutes minutes_left = duration_cast<minutes>(time_left);
seconds seconds_left = duration_cast<seconds>(time_left - minutes_left);
}
}
private:
typedef std::chrono::steady_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::duration duration;
typedef Clock::rep rep;
std::uint64_t _total_ticks;
std::uint64_t _ticks_occurred;
time_point _begin;
//...
};
std :: chrono :: यातायात में ट्रैफिक :: जब भी आप कर सकते हैं। इस तरह <chrono>
आपके लिए सभी रूपांतरण करता है। टाइपपीफ लंबे नामों के साथ टाइपिंग को कम कर सकते हैं। और समय और सेकंड में समय को तोड़ना उतना ही आसान है जितना ऊपर दिखाया गया है।
अपने उत्तर में bames53 नोट्स के रूप में, यदि आप मेरी <chrono_io>
सुविधा का उपयोग करना चाहते हैं, तो यह भी अच्छा है। आपकी ज़रूरतें इतनी सरल हो सकती हैं कि आप नहीं चाहते हैं। यह एक निर्णय कॉल है। bames53 का जवाब एक अच्छा जवाब है। मैंने सोचा कि ये अतिरिक्त विवरण भी उपयोगी हो सकते हैं।
संपादित
मैंने गलती से ऊपर कोड में एक बग छोड़ दिया है। और उपर्युक्त कोड को पैच करने के बजाय, मैंने सोचा कि यह बग को इंगित करना और यह दिखाने के लिए <chrono>
का उपयोग करना एक अच्छा विचार होगा।
बग यहाँ है:
duration time_left = time_taken * static_cast<rep>(1/percent_done - 1);
और यहाँ:
typedef Clock::duration duration;
अभ्यास steady_clock::duration
में आमतौर पर एक अभिन्न प्रकार के आधार पर किया जाता है। <chrono>
इसे rep
(प्रतिनिधित्व के लिए संक्षिप्त) कहते हैं। और जब percent_done
50% से अधिक है, तो time_taken
द्वारा गुणा किया जाने वाला कारक 1 से कम होने वाला है। और rep
अभिन्न है, जो 0 तक कास्ट हो जाता है। इसलिए यह progress_bar
केवल पहले 50% के दौरान अच्छा व्यवहार करता है और भविष्यवाणी करता है 0 बार पिछले 50% के दौरान छोड़ दिया।
इसे ठीक करने की कुंजी duration
एस में यातायात के लिए है जो पूर्णांक के बजाय फ़्लोटिंग पॉइंट पर आधारित है। और <chrono>
ऐसा करना बहुत आसान बनाता है।
typedef std::chrono::steady_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::period period;
typedef std::chrono::duration<float, period> duration;
duration
अब steady_clock::duration
रूप में एक ही टिक अवधि है लेकिन प्रतिनिधित्व के लिए एक float
उपयोग करता है।
duration time_left = time_taken * (1/percent_done - 1);
यहाँ पूरे पैकेज है फिर से इन सुधारों के साथ: और अब time_left
के लिए गणना बंद static_cast छोड़ सकते हैं एक छोटे से परीक्षण की तरह
class progress_bar
{
public:
progress_bar(uint64_t ticks)
: _total_ticks(ticks), _ticks_occurred(0),
_begin(std::chrono::steady_clock::now())
// ...
{}
void tick()
{
using namespace std::chrono;
// test to see if enough progress has elapsed
// to warrant updating the progress bar
// that way we aren't wasting resources printing
// something that hasn't changed
if (/* should we update */)
{
// somehow _ticks_occurred is updated here and is not zero
duration time_taken = Clock::now() - _begin;
float percent_done = (float)_ticks_occurred/_total_ticks;
duration time_left = time_taken * (1/percent_done - 1);
minutes minutes_left = duration_cast<minutes>(time_left);
seconds seconds_left = duration_cast<seconds>(time_left - minutes_left);
std::cout << minutes_left.count() << "m " << seconds_left.count() << "s\n";
}
}
private:
typedef std::chrono::steady_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::period period;
typedef std::chrono::duration<float, period> duration;
std::uint64_t _total_ticks;
std::uint64_t _ticks_occurred;
time_point _begin;
//...
};
कुछ भी नहीं है ... ;-)
"टिक" का कारण प्रगति का प्रतिनिधित्व करना है, यानी: मेरे पास पूरा करने के लिए 1,000,000 ऑपरेशन (टिक) हैं। जो मैं बता सकता हूं उससे बूस्ट में 'chrono_io' है। क्या आप इसका उपयोग करने की सलाह देंगे? – nerozehl
ओह, "टिक" काम की एक इकाई का प्रतिनिधित्व करता है, समय की इकाई नहीं? यदि हां, तो मैंने आपके प्रश्न को गलत समझा। मैंने गलती से "घड़ी टिक" पढ़ा। बूस्ट '' '' की एक अधिकृत प्रति है। यदि आपको यह उपयोगी लगता है तो इसका उपयोग करना ठीक होना चाहिए। मैं भविष्य के मानक के लिए '' प्रस्तावित कर रहा हूं, इसलिए इस पर प्रतिक्रिया रखना अच्छा होगा। –
हां काम की एक इकाई होने पर टिकटें .. मुझे लगता है कि मुझे और स्पष्ट होना चाहिए था, मुझे उस पर परेशानी के लिए खेद है। आपका बहुत बहुत धन्यवाद! :) – nerozehl