There is a tivemal structure, which has two fields

long int sec; long int usec; 

I need to take another from one timeval structure and divide it into a third one, that is, to find: (timeval - timeval) / timeval

  • you can, in long long convert long long t = sec*1000 + usec or something like that and do what you want :) - pavel
  • And you can in double, recalculate as sec + usec/1000.0 , then back. - Zealint
  • @pavel I don `t know, I have a long int already 8 bytes, will there be no loss of capacity? - van9petryk
  • one
    purely for clarification, but the u prefix is ​​usually used for microseconds . Actually gnu.org/software/libc/manual/html_node/Elapsed-Time.html : "long int tv_usec: it is the number of microseconds . It is always less than one million. " - Monah Tuk
  • one
    @ van9petryk exactly! because it is not milliseconds (10 ^ -3), but microseconds (10 ^ -6). In general, the topic is renamed. For correctness. - Monah Tuk

3 answers 3

Having the following structure:

 struct CustomTime { long long secs; long long msecs; }; 

The difference is quite simple:

 CustomTime difference(CustomTime first, CustomTime second) { CustomTime res; res.secs = first.secs - second.secs; res.msecs = first.msecs - second.msecs; if(res.secs >= 0 && res.msecs < 0) { --res.secs; res.msecs += 1000; } else if(res.secs < 0) { if(res.msecs < 0) res.msecs = -res.msecs; else { ++res.secs; res.msecs = res.secs != 0 ? 1000 - res.msecs : res.msecs - 1000; } } return res; } 

But with the division is not so simple. Because possible overflow and we use long long , then we need to reduce our calculations, and for this, logarithms exist. By trial and error I came to this method:

 CustomTime division(CustomTime first, CustomTime second) { auto logMsec = log(first.secs + first.msecs / 1000.0) - log(second.secs + second.msecs / 1000.0); double logSecs = logMsec < log(1000) ? 0.0 : logMsec - log(1000); CustomTime res; if(logSecs < 0.000001) { res.secs = 0; res.msecs = exp(logMsec); } else { auto dSecs = exp(logSecs); res.secs = dSecs; res.msecs = (dSecs - res.secs) * 1000; } return res; } 
  • I think direct conversion to long double gives less error. - pavel
  • @pavel, and how can you convert to long double ? long long * long long may be longer long double - ixSci
  • Well, for example, so long double val = (long double) first * second; And in the sense of more, the maximum of the product is less than 2^128 ( 2^64 ). long double much more than an exponent allows. And accuracy is not worse than logarithm. - pavel
  • in fact, with such a conversion, we will lose only the low bits that do not fit into the mantissa, or do I not understand something? - pavel
  • @pavel, no, I'm slowing down at the end of the day, I have to look at how much your method will lose, check? I checked my own on several variants - I did it all right. - ixSci

In one second 1000 milliseconds, then there are 2 options: 1. Translate everything in milliseconds and count. 2. find the function or overload the operators "-" and "/". https://habrahabr.ru/post/132014/

    The difference can be calculated as

     struct timeval tm_diff (struct timeval tm1, struct timeval tm2) { struct timeval diff; int neg = tm1.tv_sec < tm2.tv_sec || (tm1.tv_sec == tm2.tv_sec && tm1.tv_usec < tm2.tv_usec); if (neg) { // SWAP diff = tm1; tm1 = tm2; tm2 = diff; } diff.tv_sec = tm1.tv_sec - tm2.tv_sec; if (tm1.tv_usec < tm2.tv_usec) { tm1.tv_usec += 1000000; diff.tv_sec--; } diff.tv_usec = tm1.tv_usec - tm2.tv_usec; if (neg) diff.tv_sec = -diff.tv_sec; return diff; } 

    well, and to divide, probably really better in double , translating in microseconds

     double t1 = tm1.tv_sec + tm1.tv_usec * 1000000, t2 = tm2.tv_sec + ....; 

    PS

    Of course, wrong, you need to multiply seconds ...

     double t1 = tm1.tv_sec * 1.0E6 + tm1.tv_usec, t2 = tm2.tv_sec * 1.0E6 + ....; 
    • Here you need to be careful: either accuracy or overflow. Or obviously multiply by 10e6 (or 1000000.0 ). Plus, in your example, you usec for some reason, multiply more :) although you need sec . In any case - purely theoretically, when multiplying, you can go beyond the bit grid, then you need: tm1.tv_sec + tm1.tv_usec / 10e6 , but then accuracy is lost. Although ... whether much: usec encodes, in fact, the fractional part of a second to within one millionth, double here should be enough for the eyes. - Monah Tuk
    • By the way, the difference can be made even easier specifically for this structure: secAB = usecA > usecB ? (secA - secB) : (secA - secB - 1); secAB = usecA > usecB ? (secA - secB) : (secA - secB - 1); usecAB = usecA > usecB ? (usecA - usecB) : (1000000 - usecB + usecA); - Monah Tuk
    • @MonahTuk, of course, you need to multiply the seconds ... and it’s better to use floating arithmetic right away. - avp pm
    • double here is not quite suitable: it is 64 bits, exactly like tv_sec (although there can be anything, for the most part). tv_usec can have a maximum value of 999999. It needs 20 bits, which is how to pack 64 bits and 20 bits to 64 bits - something is lost somewhere. At a minimum, time_t can store the number of seconds since the beginning of the epoch, and this is already 1463671291 (it was a few seconds ago :)), if multiplied by 1e16, it is already beyond 64 bits. - Monah Tuk
    • @MonahTuk, imho here you were wrong. While we do not lose anything. The mantissa (EMNIP) in double 52 bits. Multiply by 10 ^ 6. So 32 bits (and now still 31) roughly speaking we shift by 20. Everything fits. And even 32 bits (ie, 69 more years after 2038) will not cause loss of accuracy here either. - avp