Как получить продолжительность в виде int milli и float секунд из <chrono>?

94

Я пытаюсь использовать библиотеку хронографов для таймеров и продолжительности.

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

Мне нужно получить frameDeltaпродолжительность в миллисекундах и секундах с плавающей запятой.

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

EddieV223
источник
Назначьте длительность длительности с соотношением секунд (или миллисекунд), а затем вызовите countего ...
K-балл
автоматическая дельта = продолжительность_каста <секунды> (frameDelta) .count (); Как это? Возвращает long long не поплавок.
EddieV223
3
@ K-балл, если длительность имеет более высокое разрешение, чем тип, которому вы ее назначаете, тогда назначение будет неправильно сформировано, чтобы избежать потери точности. Вам нужно использовать продолжительность с представлением с плавающей запятой или использоватьduration_cast
Джонатан Уэйкли
@JonathanWakely: О, тогда я неправильно его использовал! :(
K-балл

Ответы:

154

Это то, что вы ищете?

#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. Было бы здорово, если бы вы могли добавить в свой код дополнительные детали. Это поможет другим людям понять, чего вы пытаетесь достичь и как работают ваши решения. Благодарность!
Луис Крус,
К вашему сведению - это был САМЫЙ ЯСНЫЙ, самый полезный пример из десятков, которые я рассмотрел. Спасибо за то, что сделали понятными вечно запутанные функции хронографа.
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';
}
Крис Дрю
источник