Getting duration value as double - c++

Let's say, I have following duration value:
auto duration=12h+15min+99s+99ms;
I want to know how many hours that is (as double value).
When I do auto hours=std::chrono::duration_cast<std::chrono::hours>(duration), I get hours.count() which is int. What is the right way to get the value for the whole duration expressed as double?

using namespace std::chrono;
// Create a double-based hours duration unit
using dhours = duration<double, hours::period>;
// Assign your integral-based duration to it
dhours h = 12h+15min+99s+99ms;
// Get the value
cout << h.count();
Or alternatively, simply divide your integral based duration by one double-based hours:
cout << (12h+15min+99s+99ms)/1.0h << '\n';

#include<iostream>
#include<chrono>
using namespace std::chrono_literals;
int main() {
auto duration = 12.0h+15min+99s+99ms;
std::cout << std::chrono::duration_cast<std::chrono::duration<long double,std::ratio<3600,1>>>(duration).count();
}

Related

Raspberry pi, C++ chrono function, operations on values?

I am beginning in C++ and with the "chrono" function, and I'd like to use it to get the speed of a motor.
For that, I have a coding wheel linked to a motor, an optocoupler is used to gather the square signal generated by the coding wheel.
Therefore, my raspberry pi receive a square signal which speed depends on the motor speed.
I used the chrono function to try to calculate the duration of the frequency of the square signal.
I achieved to have the duration of each signal (almost) which is 7ms.
I'd like to simply extract the frequency through the formula 1/F (therefore, 1/0.007 = 142.85).
I've been eating the documentation of the chrono function for a week, and I still don't get it at all...
Apparently, all the answers are here, but I don't understand that, I'm still a beginner in C++ :( https://en.cppreference.com/w/cpp/chrono
This has been REALLY usefull, but limited : https://www.code57.com/cplusplus-programming-beginners-tutorial-utilities-chrono/
If I understand right, the "value" of 7ms is stored in an "object"...
How can I simply get it out of there and put it in a standard variable so I can divide, multiply and do whatever I want with it?
Here is the interresting part of the C++ code :
#include <iostream>
#include <wiringPi.h>
#include <cstdio>
#include <csignal>
#include <ctime>
#include <chrono>
// global flag used to exit from the main loop
bool RUNNING = true;
bool StartTimer = false;
//int timer = 0;
std::chrono::steady_clock::time_point BeginMeasurement; //chrono variable representing the beginning of the measurement of a motor speed
//some more code in here, but nothing exceptionnal, just calling the interruption when needed
//interruption function for counting the motor speed
void RPMCounter(){
using namespace std;
using namespace std::chrono;
if (StartTimer == true){
StartTimer = false;
steady_clock::duration result = steady_clock::now()-BeginMeasurement;
if (duration_cast<milliseconds>(result).count() < 150){
double freq;
//cout.precision(4);
std::cout << "Time = " << duration_cast<milliseconds>(result).count() << " ms" << '\n';
// I would like the next line to work and give me the frequency of the detection...
freq = 1/(duration_cast<milliseconds>(result).count()/1000);
std::cout << "Frequency = " << freq << " Hz" << '\n';
}
}
else{
BeginMeasurement = steady_clock::now();
StartTimer = true;
}
}
Here is the result in my command prompt :
the value of 7ms increases because I stopped the motor, therefore, it was turning slower until stopping ;)
Edit :
Thanks to Howard Hinnant and Ted Lyngmo, My code now looks like this :
void RPMCounter(){
using namespace std;
using namespace std::chrono;
if (StartTimer == true){
StartTimer = false;
duration<double> result = steady_clock::now() - BeginMeasurement;
if (result < milliseconds{150}){
double freq;//= 1s / result;
//cout.precision(4);
std::cout << "Time = " << duration_cast<milliseconds>(result).count() << " ms" << '\n';
freq = (1.0/(duration<double>{result}.count()/1000))/1000;
std::cout << "Frequency = " << freq << " Hz" << '\n';
}
}
else{
BeginMeasurement = steady_clock::now();
StartTimer = true;
}
}
and it seems to give me a correct frequency.
As i'm a beginner, I'll surely understand all that better in a while and improve it :)
(basically, I'm not exactly sure of what I wrote mean... like the "::" and other ways of :)
The rest of my coding should be more basic and allow me to learn all the tweaks of C++
if (duration_cast<milliseconds>(result).count() < 150){
You can simplify this with:
if (result < 150ms)
Or if you're in C++11:
if (result < milliseconds{150})
The advantage is that you don't have to truncate result to a courser precision, and the code is just easier to read.
freq = 1/(duration_cast<milliseconds>(result).count()/1000);
Instead:
using dsec = duration<double>; // define a double-based second
auto freq = 1/dsec{result}.count();
This could also be written:
auto freq = 1/duration<double>{result}.count();
In any event, this converts result straight to double-based seconds, and inverts that value using floating point arithmetic. The original code uses integral division resulting in an integral result that is always rounding down to 0. I.e. 1/10 == 0, whereas 1/10. == 0.1.
I'd make the result a double based duration:
auto BeginMeasurement = std::chrono::steady_clock::now();
// some work
// a double based duration
std::chrono::duration<double> result = std::chrono::steady_clock::now() - BeginMeasurement;
You can then divide the duration 1s with result to get the frequency:
using namespace std::chrono_literals;
double freq = 1s / result;
std::cout << freq << " Hz\n";
Howard Hinnant pointed out that from C++14 you can make it even easier for youself by changing the dividend from an integer based duration, 1s, to a double based duration, 1.0s, and let result be deduced using auto:
auto result = std::chrono::steady_clock::now() - BeginMeasurement;
double freq = 1.0s / result;
Demo

Cannot exit While loop

I want to exit While loop, when variable "duration" reaches 5 sec.
Variable "duration" always =0
#include <iostream>
#include <Windows.h>
#include <chrono>
using namespace std;
DOUBLE duration;
int main()
{
using clock = std::chrono::system_clock;
using sec = std::chrono::duration <double>;
const auto before = clock::now();
while (duration < 5.0)
{
const auto after = clock::now();
const sec duration = after - before;
std::cout << "It took " << duration.count() << "s" << std::endl;
}
std::cout << "After While Loop "; //Never reaches this line!!!!!
return 0;
}
Actual output:.
.
it took 9.50618s
it tool 9.50642s
.
I expected while loop to exit at 5.0 or higher.
display variable always shows 0.
You are using two separate variables named duration.
using sec = std::chrono::duration <double>; // number 1
const auto before = clock::now();
while (duration < 5.0) // checking number 1, which is not changed during looping
{
const auto after = clock::now();
const sec duration = after - before; // number 2, created afresh in each iteration
std::cout << "It took " << duration.count() << "s" << std::endl;
}
So, what you are checking in the loop condition is not what gets changed in the loop body.
You have two variables called duration:
DOUBLE duration;
and in while loop:
const sec duration = after - before;
During evaluation of while statement you are checking the first one that is never set or changed.
Inside while loop body you're creating a new variable that shadows global variable. See https://en.wikipedia.org/wiki/Variable_shadowing
Insead you shouldn't declare a new variable but use one declared before entering to the while loop.
There are two issues here:
Declaring a local variable with the same name that of the global variable makes them two separate entities, which may get quiet confusing. This phenomenon is called as Variable shadowing.
You are comparing the duration variable which is actually an object of class sec and not an integer or float. So, for comparing the value in duration just do duration.count() to make it comparable to integer or float values.
Here, in your code, the global duration variable is never changed because you are declaring a new variable inside the while loop. The duration variable that is been checked in the while condition is the global duration variable but you expect it to be the duration variable inside the loop.
There are two possible solutions:
Either make the two duration variables the same.
Or break the while(1) loop when the duration variable hold value >= 5,
Solution 1 code looks like this:
#include <iostream>
#include <Windows.h>
#include <chrono>
using namespace std;
int main()
{
using clock = std::chrono::system_clock;
using sec = std::chrono::duration <double>;
sec duration;
const auto before = clock::now();
while (duration.count() < 5.0)
{
const auto after = clock::now();
duration = after - before;
std::cout << "It took " << duration.count() << "s" << std::endl;
}
std::cout << "After While Loop "; //Never reaches this line!!!!!
return 0;
}
Solution 2 code looks like this:
#include <iostream>
#include <Windows.h>
#include <chrono>
using namespace std;
int main()
{
using clock = std::chrono::system_clock;
using sec = std::chrono::duration <double>;
const auto before = clock::now();
while (1) // Soln 1: while(1)
{
const auto after = clock::now();
const sec duration = after - before;
std::cout << "It took " << duration.count() << "s" << std::endl;
if(duration.count() >= 5)
break;
}
std::cout << "After While Loop "; //Never reaches this line!!!!!
return 0;
}

convert minutes::rep to hours::rep

How should I proceed to convert std::chrono::minutes::rep type value to hours representation.
#include <iostream>
#include <chrono>
using namespace std;
using namespace std::chrono;
int main() {
minutes::rep time = 4;
std::cout << time; // outputs as minutes, need in hours
// duration cast doesn't seems to work here because it
// needs minutes instead of minutes::rep probably
return 0;
}
minutes::rep time = 4;
std::cout << time; // outputs as minutes, need in hours
Because time is just an (implementation-defined) integer type, it has nothing to do with minutes or hours, and doesn't know anything about underlying time representation.
You want to stay in the duration realm:
minutes time{4};
auto as_hours = std::duration_cast<hours>(time);
std::cout << as_hours.count(); // prints 0
Or, likely:
auto as_hours_dbl = std::duration_cast<duration<double, hours::period>>(time);
std::cout << as_hours_dbl.count(); // prints 0.0666667

Proper method of using std::chrono

While I realize this is probably one of many identical questions, I can't seem to figure out how to properly use std::chrono. This is the solution I cobbled together.
#include <stdlib.h>
#include <iostream>
#include <chrono>
typedef std::chrono::high_resolution_clock Time;
typedef std::chrono::milliseconds ms;
float startTime;
float getCurrentTime();
int main () {
startTime = getCurrentTime();
std::cout << "Start Time: " << startTime << "\n";
while(true) {
std::cout << getCurrentTime() - startTime << "\n";
}
return EXIT_SUCCESS;
}
float getCurrentTime() {
auto now = Time::now();
return std::chrono::duration_cast<ms>(now.time_since_epoch()).count() / 1000;
}
For some reason, this only ever returns integer values as the difference, which increments upwards at rate of 1 per second, but starting from an arbitrary, often negative, value.
What am I doing wrong? Is there a better way of doing this?
Don't escape the chrono type system until you absolutely have to. That means don't use .count() except for I/O or interacting with legacy API.
This translates to: Don't use float as time_point.
Don't bother with high_resolution_clock. This is always a typedef to either system_clock or steady_clock. For more portable code, choose one of the latter.
.
#include <iostream>
#include <chrono>
using Time = std::chrono::steady_clock;
using ms = std::chrono::milliseconds;
To start, you're going to need a duration with a representation of float and the units of seconds. This is how you do that:
using float_sec = std::chrono::duration<float>;
Next you need a time_point which uses Time as the clock, and float_sec as its duration:
using float_time_point = std::chrono::time_point<Time, float_sec>;
Now your getCurrentTime() can just return Time::now(). No fuss, no muss:
float_time_point
getCurrentTime() {
return Time::now();
}
Your main, because it has to do the I/O, is responsible for unpacking the chrono types into scalars so that it can print them:
int main () {
auto startTime = getCurrentTime();
std::cout << "Start Time: " << startTime.time_since_epoch().count() << "\n";
while(true) {
std::cout << (getCurrentTime() - startTime).count() << "\n";
}
}
This program does a similar thing. Hopefully it shows some of the capabilities (and methodology) of std::chrono:
#include <iostream>
#include <chrono>
#include <thread>
int main()
{
using namespace std::literals;
namespace chrono = std::chrono;
using clock_type = chrono::high_resolution_clock;
auto start = clock_type::now();
for(;;) {
auto first = clock_type::now();
// note use of literal - this is c++14
std::this_thread::sleep_for(500ms);
// c++11 would be this:
// std::this_thread::sleep_for(chrono::milliseconds(500));
auto last = clock_type::now();
auto interval = last - first;
auto total = last - start;
// integer cast
std::cout << "we just slept for " << chrono::duration_cast<chrono::milliseconds>(interval).count() << "ms\n";
// another integer cast
std::cout << "also known as " << chrono::duration_cast<chrono::nanoseconds>(interval).count() << "ns\n";
// floating point cast
using seconds_fp = chrono::duration<double, chrono::seconds::period>;
std::cout << "which is " << chrono::duration_cast<seconds_fp>(interval).count() << " seconds\n";
std::cout << " total time wasted: " << chrono::duration_cast<chrono::milliseconds>(total).count() << "ms\n";
std::cout << " in seconds: " << chrono::duration_cast<seconds_fp>(total).count() << "s\n";
std::cout << std::endl;
}
return 0;
}
example output:
we just slept for 503ms
also known as 503144616ns
which is 0.503145 seconds
total time wasted: 503ms
in seconds: 0.503145s
we just slept for 500ms
also known as 500799185ns
which is 0.500799 seconds
total time wasted: 1004ms
in seconds: 1.00405s
we just slept for 505ms
also known as 505114589ns
which is 0.505115 seconds
total time wasted: 1509ms
in seconds: 1.50923s
we just slept for 502ms
also known as 502478275ns
which is 0.502478 seconds
total time wasted: 2011ms
in seconds: 2.01183s

Add time duration to C++ timepoint

I have a starting timepoint in milliseconds like so:
using namespace std::chrono;
typedef time_point<system_clock, milliseconds> MyTimePoint;
MyTimePoint startTimePoint = time_point_cast<MyTimePoint::duration>(system_clock::time_point(steady_clock::now()));
Now I will have a certain number of hours that I want to add or subtract to the startTimePoint.
int numHours = -5//or 5 etc (Can be a plus or minus number)
How can I add this abount of time to the original startTimePoint??
If you want to add five hours to startTimePoint, it's boringly simple:
startTimePoint += hours(5); // from the alias std::chrono::hours
Live example.
By the way, you're trying to convert a steady_clock::now() into a system_clock::time_point, which shouldn't even compile. Change the steady_clock::now() to system_clock::now() and you should be good to go.
Here I have used time in minutes you can go for anything that you want from the user.
So the below is the simple programme using chrono
#include <iostream>
#include <chrono>
using namespace std;
int main() {
using clock = std::chrono::system_clock;
clock::time_point nowp = clock::now();
cout<<"Enter the time that you want to add in minutes"<<endl;
int time_min;
cin>>time_min;
cin.ignore();
clock::time_point end = nowp + std::chrono::minutes(time_min);
time_t nowt = clock::to_time_t ( nowp );
time_t endt = clock::to_time_t ( end);
std::cout << " " << ctime(&nowt) << "\n";
std::cout << ctime(&endt) << std::endl;
return 0;
}
Convert time_point to duration or duration to time_point without intermediate.
It is inherently impossible to convert a time_point to duration or back directly.
Many examples use time_t as intermediate, which is a fine method.
I use the method that uses the time_point 'zero' as a helper.
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
int main(int argc, char *argv[])
{
using namespace std::chrono;
system_clock::time_point zero; // initialised to zero in constructor
system_clock::time_point tp_now; // now as time_point
duration<int, ratio<1>> dur_now; // now as duration
system_clock::time_point tp_future; // calculated future as time_point
// The objective is to sleep_until the system time is at the next 5 minutes
// boundary (e.g. time is 09:35)
tp_now = system_clock::now(); // What time is it now?
cout << "tp_now = " << tp_now.time_since_epoch().count() << endl;
// It is not possible to assign a time_point directly to a duration.
// but the difference between two time_points can be cast to duration
dur_now = duration_cast<seconds>(tp_now-zero); // subtract nothing from time_point
cout << "dur_now = " << dur_now.count() << endl;
// Instead of using seconds granularity, I want to use 5 minutes
// so I define a suitable type: 5 minutes in seconds
typedef duration<int,ratio<5*60>> dur5min;
// When assigning the time_point (ok: duration) is truncated to the nearest 5min
dur5min min5 = duration_cast<dur5min>(tp_now-zero); // (Yes, I do it from time_point again)
cout << "min5 ('now' in 5min units) = " << min5.count() << endl;
// The next 5 min time point is
min5 += dur5min{1};
cout << "min5 += dur5min{1} = " << min5.count() << endl;
// It is not possible to assign a duration directly to a time_point.
// but I can add a duration to a time_point directly
tp_future = zero + min5;
cout << "tp_future = " << tp_future.time_since_epoch().count() << endl;
// to be used in e.g. sleep_until
// std::this_thread::sleep_until(tp_future);
return 0;
}
Thanks to Carsten's solution I managed to create function:
#include <chrono>
auto getTimeDurationMovedWith(std::chrono::hours hours2move)
{
using namespace std::chrono;
auto current_time = system_clock::now();
decltype(current_time) zeroTime; // no better solution to move time found in stackoverflow
return chrono::duration_cast<microseconds>(
current_time - zeroTime + hours(hours2move));
}
And it can be used like that:
auto tmp = getTimeDurationMovedWith(chrono::hours(-10));
cout << tmp.count() << endl;