Як отримати тривалість, як int milli's та float seconds з <chrono>?


94

Я намагаюся використовувати бібліотеку chrono для таймерів та тривалості.

Я хочу мати можливість мати Duration frameStart;(від запуску програми) і Duration frameDelta;(час між кадрами)

Мені потрібно вміти отримувати frameDeltaтривалість як мілісекунди та плаваючі секунди.

Як це зробити за допомогою нових <chrono>бібліотек c ++ 11 ? Я працював над цим і гуглив (інформація скупа). Код важко шаблонований і вимагає спеціальних складок та іншого, я не можу зрозуміти, як правильно використовувати цю бібліотеку.


Призначте тривалість тривалості із співвідношенням секунд (або мілісекунд), а потім зателефонуйте countїй ...
K-ballo

авто дельта = тривалість_запису <секунди> (frameDelta) .count (); Подобається це? Він повертається довго довго, а не поплавок.
EddieV223

3
@ K-ballo, якщо тривалість має вищу роздільну здатність, ніж тип, якому ви призначаєте, то призначення буде неправильно сформоване, щоб уникнути втрати точності. Вам потрібно використовувати тривалість із поданням із плаваючою комою, або використовуватиduration_cast
Джонатан Уейклі

@JonathanWakely: О, тоді я використовую це неправильно! :(
K-ballo

Відповіді:


153

Це те, що ви шукаєте?

#include <chrono>
#include <iostream>

int main()
{
    typedef std::chrono::high_resolution_clock Time;
    typedef std::chrono::milliseconds ms;
    typedef std::chrono::duration<float> fsec;
    auto t0 = Time::now();
    auto t1 = Time::now();
    fsec fs = t1 - t0;
    ms d = std::chrono::duration_cast<ms>(fs);
    std::cout << fs.count() << "s\n";
    std::cout << d.count() << "ms\n";
}

що для мене роздруковує:

6.5e-08s
0ms

2
чому не використовувати autoна fsта d?
TemplateRex

27
@rhalbersma: Використання autoбуде чудовим для d, як результат duration_cast<ms>є ms. Однак for fs autoне буде доречним, оскільки результат t1-t0має тип, high_resolution_clock::durationякий не обов'язково є тим самим типом, що і duration<float>. Наприклад, у моїй системі це так duration<long long, nano>. Отже, на цьому рядку відбувається неявне перетворення з інтегрального на nanosecondsплаваючий seconds, лише тому, що тип призначення вказаний з fsec.
Говард Хіннант

2
Це корисна інформація. Просто цікаво: чи auto fs = std::chrono::duration_cast<fsec>(t1 - t0);буде педантом надмірне?
TemplateRex

@rhalbersma: Це працювало б так само добре, і робило б точно те саме. Щодо того, якому слід віддавати перевагу, це, на мій погляд, цілком стилістично.
Говард Хіннант

2
майте на увазі, що в деяких сценаріях реального світу (наприклад, компілятор ms та бібліотеки) 'high_resolution_clock' буде пропускати час в порядку мікросекунд, і цей код виплюне нулі,
jheriko

19

Вгадуючи, про що саме ви просите. Я припускаю, що за мілісекундним таймером кадру ви шукаєте щось таке, що діє наступним чином,

double mticks()
{
    struct timeval tv;
    gettimeofday(&tv, 0);
    return (double) tv.tv_usec / 1000 + tv.tv_sec * 1000;
}

але використовує std::chronoзамість цього,

double mticks()
{
    typedef std::chrono::high_resolution_clock clock;
    typedef std::chrono::duration<float, std::milli> duration;

    static clock::time_point start = clock::now();
    duration elapsed = clock::now() - start;
    return elapsed.count();
}

Сподіваюся, це допомагає.


Ласкаво просимо до Stack Overflow. Було б чудово, якби ви могли надати додаткові деталі для свого коду. Це допомогло б іншим людям зрозуміти, чого ви намагаєтесь досягти, і як працюють ваші рішення. Дякую!
Луїс Круз,

FYI - це був НАЙЯСНІШИЙ, найкорисніший приклад з десятків, які я переглянув. Дякуємо, що зробили незрозумілі функції хронометра зрозумілими.
SMGreenfield

15

Я не знаю, що означають "мілісекунди та плаваючі секунди", але це повинно дати вам уявлення:

#include <chrono>
#include <thread>
#include <iostream>

int main()
{
  auto then = std::chrono::system_clock::now();
  std::this_thread::sleep_for(std::chrono::seconds(1));
  auto now = std::chrono::system_clock::now();
  auto dur = now - then;
  typedef std::chrono::duration<float> float_seconds;
  auto secs = std::chrono::duration_cast<float_seconds>(dur);
  std::cout << secs.count() << '\n';
}

Я здогадуюсь він хоче фактичний countяк float?
K-ballo

1
Ось що друкується в кінці. Але я не знав, чи хоче він мілісекунди як ціле число, чи мілісекунди після секунди, чи що.
Джонатан Уейклі

Я хотів би мати можливість отримати від chrono :: duration тривалість, представлену як int мілісекунди, або плаваючі секунди (частка секунди)
EddieV223

Відповідь Говарда робить саме це
Джонатан Уейклі

8

У стилі AAA з використанням явно набраної ідіоми ініціалізатора :

#include <chrono>
#include <iostream>

int main(){
  auto start = std::chrono::high_resolution_clock::now();
  // Code to time here...
  auto end = std::chrono::high_resolution_clock::now();

  auto dur = end - start;
  auto i_millis = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
  auto f_secs = std::chrono::duration_cast<std::chrono::duration<float>>(dur);
  std::cout << i_millis.count() << '\n';
  std::cout << f_secs.count() << '\n';
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.