getting cpu frequency (cycles per second)- 3 different ways: - c++

I have three calculation to get the curent cpu frequency: (cycles per second)
_initialCycles = rdtsc(); //rdtsc function calculates the cpu cycles since init.
first:
------
unsigned int initialMillisec = (_timeVal.tv_sec)*1000+(_timeVal.tv_usec)/1000;
unsigned int cps1 = ((_initialCycles / initialMillisec) * 1000);
second:
-------
double initialMillisec2 = (_timeVal.tv_sec)*1000+(_timeVal.tv_usec)/1000.0;
unsigned int cps2 = (unsigned int)(_initialCycles / initialMillisec2 * 1000.0);
third:
------
unsigned long long initialUsec3 =
((unsigned long long)(_timeVal.tv_sec))*1000000+_timeVal.tv_usec) ;
unsigned int cps3 = (unsigned int)((_initialCycles / initialUsec3)* 1000000.0);
the thing is, cps1 cps2 cps3 suppose to have the same value, more or less..
but they don't. I get:
cps1 = 2824048000
cps2 = 3824609671
cps3 = 8000000
anyone knows why?

Your problem with integer types is in roundings. When you divide by some big number you loose significant digits. So, you should change the operation order between the multiplication and the division. First you should multiply by 1000 (or 1000000 in the case of long long) and only then divide.
Some examples of loosing the accuracy with the integers:
321 / 20 * 20 = 320;
321 / 75 * 75 = 300;
321 / 112 * 112 = 224

There are many other threads and processes running at the same time and the OS scheduler might inter fear with this method of measuring the frequency.
Try using the "cpufreq" utility to accurately get the current clock speed.

Operator precedence and implicit conversions.
Of course you need to make sure the operators get evaluated in the order you desire. My best advice: add parens if you would have to think twice to know the order without parens.
Then: you need to convert the ints to floats early, or you'll end up with integer division and ditto rounding errors.
unsigned int initialMillisec = _timeVal.tv_sec*1000 + _timeVal.tv_usec/1000;
unsigned int cps1 = (1.0 * _initialCycles / initialMillisec) * 1000.0;
would be my suggestion

Related

I have piece of code that gets duration from a FILETIME struct. What does it mean?

I have this function
void prtduration(const FILETIME *ft_start, const FILETIME *ft_end)
{
double duration = (ft_end->dwHighDateTime - ft_start->dwHighDateTime) *
(7 * 60 + 9 + 496e-3)
+ (ft_end->dwLowDateTime - ft_start->dwLowDateTime) / 1e7;
printf("duration %.1f seconds\n", duration);
system("pause");
}
Could anybody explain the working of the following part of the code?
(ft_end->dwHighDateTime - ft_start->dwHighDateTime) *
(7 * 60 + 9 + 496e-3)
+ (ft_end->dwLowDateTime - ft_start->dwLowDateTime) / 1e7;
Wow! What an obfuscated piece of code. Let us try to simplify it:
// Calculate the delta
FILETIME delta;
delta.dwHighDateTime = ft_end->dwHighDateTime - ft_start->dwHighDateTime;
delta.dwLowDateTime = ft_end->dwLowDateTime - ft_start->dwLowDateTime;
// Convert 100ns units to double seconds.
double secs = delta.dwHighDateTime * 429.496 + delta.dwLowDateTime/1E7
In actual fact I think this is wrong. It should be:
double secs = delta.dwHighDateTime * 429.4967296 + delta.dwLowDateTime/1E7
Or even more clearly:
double secs = (delta.dwHighDateTime * 4294967296. + delta.dwLowDateTime)/10E6
What is happening is that the high time is being multiplied by 2**32 (which converts to 100ns units then divided by 100ns to give seconds.
Note that this is still wrong because the calculation of delta is wrong (in the same way as the original). If the subtraction of the low part underflows, it fails to borrow from the high part. See Microsoft's documentation:
It is not recommended that you add and subtract values from the FILETIME structure to obtain relative times. Instead, you should copy the low- and high-order parts of the file time to a ULARGE_INTEGER structure, perform 64-bit arithmetic on the QuadPart member, and copy the LowPart and HighPart members into the FILETIME structure.
Or actually, in this case, just convert the QuadPart to double and divide. So we end up with:
ULARGE_INTEGER start,end;
start.LowPart = ft_start->dwLowDateTime;
start.HighPart = ft_start->dwHighDateTime;
end.LowPart = ft_end->dwLowDateTime;
end.HighPart = ft_end->dwHighDateTime;
double duration = (end.QuadPart - start.QuadPart)/1E7;
Aside: I bet the reason that the failure to borrow has never been spotted is that the code has never been asked to print a duration of greater than 7 minutes 9 seconds (or if it has, nobody has looked carefully at the result).
7 is very approximately frequency when FileTime variable changes its value. Namely, every 7 (+-3 or even more) minutes it increases on 1. Than we multiply it on 60 for getting value in seconds.
9 + 496e-3 - is time is seconds that deals somehow with compilation (from the start of the withdrawal to output in the console) that we are losing.
Really, it is very bad code and we shouldn't write like this.
However it have forced me to learn better about FileTime work.
Thanks everyone for answers, I very appreciate it.

qt returns bad math

mlAnswer = ( ( ( degreesPLato->text().toInt() * 1000000 ) * 3800 ) / answer );
is the code in quesition
mlAnswer out puts -8223, while my calculator puts out 228000
debug output
12 * 1000000 * 3800 / 200000 = -8223
all data types are ints Please tell me what I'm doing wrong.
12 * 1000000 * 3800 = 45.6 billion.
This is out of range for a 4 byte signed integer, which is what int usually is. Try using long long instead.
The default type of an integer literal is int, unless the number is too big to fit in an int. As long as you are doing math operations between ints, the results remain as ints. 12 is an int, 1000000 is an int, and 3800 is an int. When you multiply them together, the result is still an int, even though it no longer fits. Add the LL suffix to make the integer literal a long long. i.e. 12LL, 1000000LL, 3800LL, etc...
You can fix this by reordering your operations:
12 * 1000000 * 3800 / 200000
Will overflow an int, however:
12 * 1000000 / 200000 * 3800
will not.
Note that this will only give the same answer if the numerator is an integer multiple of the denominator. Using LL is a better solution on platforms that support it, but if you are constrained to a 4 byte int type, this will at least stop overflow in more situations.

Convert time input to a float to enable math functions in C++

I am asking the user to input a start time and an end time in this format: 15.45 (military time with a decimal instead of a colon) and I need to convert those times to a float to perform calculations on them. I am having trouble wrapping my mind around converting the 60 minutes of an hour to a decimal value. e.g. - User inputs start of 12.45 and end of 14.15, this should be converted to 12.75 and 14.25 respectively. How would I go about this conversion?
Also, something I believe I am more capable of figuring out, but curious anyway: how would I validate input so as not to allow a time greater than 23.59 and no time with the last two digits greater than 59?
As soon as one of the values is double, then the arithmetic will be
done in double, with double results. So you can convert the
minutes to double, using any of the three C++ syntaxes:
static_cast<double>(minutes), double(minutes) or (double)minutes,
or just divide by 60.0, rather than the integer 60. (I like to be
explicit, so I'd write double(minutes) / 60.0. And some people prefer
static_cast, even in this case.)
With regards to the validation, I'd do it before conversion; once you've
added the minutes to the hours, it's too late anyway.
just use
double time = hours + minutes / 60.0;
bool hoursValid = hours < 24; // hours are unsigned, right?
bool minutesValid = minutes < 60;
Example:
char buf[] = "9.45";
unsigned int hours, minutes;
sscanf(buf, "%d.%d", &hours, &minutes);
printf("%f", hours + minutes/60.0); // outputs 9.75
If you get double 9.45 as input, you need to #include <cmath> and split it as
hours = floor(v);
minutes = (v - hours) * 100;
You have to separate the integer and decimal components of the number. You will keep the integer part intact, then add the decimal part divided by 60 to it.
Validation is also simple once you separate into hours and minutes.
I'm going to assume your code reads the value in from the user as a string. You will need to parse the user input at the decimal point to get the hours and minutes as two separate values. Once you have that, then you can convert minutes into a fraction of an hour and add it to the number of hours.
bool military_time_valid(float a) {
int t = (int)a;
if (t >= 24)
throw std::runtime_error("invalid hours");
if (a-t >= .6)
throw std::runtime_error("invalid minutes");
}
float military_to_decimal(float a) {
int t = (int)a;
return t + (a-t)/.6;
}
float decimal_to_military(float a) {
int t = (int)a;
return t + (a-t)*.6;
}
float t = 15.45;
int h = (int) t;
float m = 100 * (t - h);
printf("%f", h + m / 60);
gives output: 15.750000
Check if h is between 0 and 23 and m is between 0 and 59.
Is there some reason you don't want to create a MilTime class and overload the arithmetic operators? That would save you from having to convert to/from all the time, and would more clearly state your intentions.

long double vs long int

I'm doing a program that calculates the probability of lotteries.
Specification is choose 5 numbers out of 47 and 1 out of 27
So I did the following:
#include <iostream>
long int choose(unsigned n, unsigned k);
long int factorial(unsigned n);
int main(){
using namespace std;
long int regularProb, megaProb;
regularProb = choose(47, 5);
megaProb = choose(27, 1);
cout << "The probability of the correct number is 1 out of " << (regularProb * megaProb) << endl;
return 0;
}
long int choose(unsigned n, unsigned k){
return factorial(n) / (factorial(k) * factorial(n-k));
}
long int factorial(unsigned n){
long int result = 1;
for (int i=2;i<=n;i++) result *= i;
return result;
}
However the program doesn't work. The program calculates for 30 seconds, then gives me Process 4 exited with code -1,073,741,676 I have to change all the long int to long double, but that loses precision. Is it because long int is too short for the big values? Though I thought long int nowadays are 64bit? My compiler is g++ win32 (64bit host).
Whether long is 64-bit or not depends on the model. Windows uses a 32-bit long. Use int64_t from <stdint.h> if you need to ensure it is 64-bit.
But even if long is 64-bit it is still too small to hold factorial(47).
47! == 2.58623242e+59
2^64 == 1.84467441e+19
although 47C5 is way smaller than that.
You should never use nCr == n!/(r! (n-r)!) directly do the calculation as it overflows easily. Instead, factor out the n!/(n-r)! to get:
47 * 46 * 45 * 44 * 43
C = ----------------------
47 5 5 * 4 * 3 * 2 * 1
this can be managed even by a 32-bit integer.
BTW, for #Coffee's question: a double only has 53-bits of precision, where 47! requires 154 bits. 47! and 42! represented in double would be
47! = (0b10100100110011011110001010000100011110111001100100100 << 145) ± (1 << 144)
42! = (0b11110000010101100000011101010010010001101100101001000 << 117) ± (1 << 116)
so 47! / (42! × 5!)'s possible range of value will be
0b101110110011111110011 = 1533939 53 bits
v
max = 0b101110110011111110011.000000000000000000000000000000001001111...
val = 0b101110110011111110010.111111111111111111111111111111111010100...
min = 0b101110110011111110010.111111111111111111111111111111101011010...
that's enough to get the exact value 47C5.
to use 64bit long, you should use long long. (as mentioned here)
KennyTM has it right, you're going to overflow no matter what type you use. You need to approach the problem more smartly and factor out lots of work. If you're ok with an approximate answer, then take a look at Stirling's approximation:
Ln(n!) ~ n Ln(n) - n
So if you have
n!/(k!*(n-k)!)
You could say that's
e(ln(n!/(k!*(n-k)!)))
which after some math (double check to make sure I got it right) is
e(n*ln(n)-k*ln(k)-(n-k)*ln(n-k))
And that shouldn't overflow (but it's an approximate answer)
It's easy to calculate binomial coefficients up to 47C5 and beyond without overflow, using standard unsigned long 32-bit arithmetic. See my response to this question: https://math.stackexchange.com/questions/34518/are-there-examples-where-mathematicians-needs-to-calculate-big-combinations/34530#comment-76389

Can anyone decipher why these two conversions to unsigned long long give different results?

LARGE_INTEGER lpPerformanceCount, lpFrequency;
QueryPerformanceCounter(&lpPerformanceCount);
QueryPerformanceFrequency(&lpFrequency);
(Count.QuadPart is a long long showing a CPU count)
(Freq.QuadPart is a long long showing frequency of Count for a second)
Attempting to print microseconds in real time.
stable output:
printf("%llu\n", ((long double)lpPerformanceCount.QuadPart/ lpFrequency.QuadPart) * 1000000);
erratic output: (result jumps incoherently front and back even if it's at first glance sane)
printf("%llu\n", 1000000 * (lpPerformanceCount.QuadPart / lpFrequency.QuadPart) + (lpPerformanceCount.QuadPart % lpFrequency.QuadPart));
EDIT: printf needed a further (unsigned long long) conversion in its input, the original code had that done by a return value of a func.
Are you sure %llu prints a reasonable double?
lpPerformanceCount.QuadPart / lpFrequency.QuadPart gives you a time, rounded to full seconds.
lpPerformanceCount.QuadPart % lpFrequency.QuadPart gives you a tick count (number ticks since last full second).
Adding a count to a time gives you.. how to put that politely... crap.
I alway use the double arithmetics, much less hassle. However, if you insist in non-FPU code, you could use:
count.QuadPart*1000000 / (freq.QuadPart*1000000)
which would overflow faster (though not a practical problem I'd assume). Fixing that up for integer arithmetics:
count.QuadPart / freq.QuadPart
+ (count.QuadPart % freq.QuadPart) * 1000000 / freq.QuadPart
(I hope that's right...)
Yes. IIUC, it should be something like:
1000000 * (lpPerformanceCount.QuadPart / lpFrequency.QuadPart) +
(lpPerformanceCount.QuadPart % lpFrequency.QuadPart) * 1000000 / lpFrequency.QuadPart
or maybe
(lpPerformanceCount.QuadPart / (lpFrequency.QuadPart / 1000000) )
The first will overflow if lpFreuency.QuadPart is high; the second will be inaccurate or even overflow if lpFrequency.QuadPart is low.