How can you switch a float to a time format? - c++

Hello I am a begineer so please be nice :)..
In C++, if I have a float like 12.5 or 13.25, how can I convert this to show as 12:30 and 13:15?
Thank you so much.

float time = ...;
Simly casting the float to an int will chop off the fractional part, leaving you with the hours.
int hour = static_cast<int>(time);
If you subtract the hours, then all that's left is the minutes as fractions of an hour. If you multiply this by 60, you get the remainder in minutes. Again, cast to an int to chop off the seconds, leaving only minutes.
int minute = static_cast<int>((time-hour)*60);
Then display the hours, and a colon. To display the minutes properly, tell it to always use a width of 2 characters, and fill in the blanks with a '0'. This makes it say 02 instead of just 2.
std::cout << hour << ':' << std::setw(2) << std::fill('0') << minute;

As with any problem, you need to break it down into its component parts and attack each one separately.
What you have:
A floating-point number of hours.
What you need:
To print the integer number of hours.
To print a ":"
To print the fractional number of hours as a proportion of 60 minutes.
So, now, we can address each part of the problem.
Let's say the input is:
const float time = 13.25;
The first part is quite easy — truncating a floating-point variable can be done using the mathematical floor function, but all you really need to do is cast to int to get the same effect:
std::cout << (unsigned int)time;
The second part is also really easy:
std::cout << ':';
The third part takes a little more work. We need to discard everything but the fractional part. We can do that by subtracting the integer part:
time - (unsigned int)time
Then we must transform the value so that instead of being a proportion of the range [0.00,1.00), it's a proportion of the range [0,60), simply by multiplying by 60:
60 * (time - (unsigned int)time)
We're left with:
const float time = 13.25;
std::cout << (unsigned int)time;
std::cout << ':';
std::cout << 60 * (time - (unsigned int)time);
// result: 13:15
(live demo)
For a general solution, we also want to show a leading zero if there's only one digit:
const float time = 12.10;
std::cout << (unsigned int)time;
std::cout << ':';
std::cout << std::setw(2) << std::setfill('0');
std::cout << 60 * ((time - (unsigned int)time) / 100);
// result: 12:06
In reality, to avoid rounding errors and possible overflows, you'd drop the float altogether and simply store integer minutes:
const unsigned int time_mins = (12*60) + 6;
std::cout << (time_mins / 60);
std::cout << ':';
std::cout << std::setw(2) << std::setfill('0');
std::cout << (time_mins % 60);
// result: 12:06
(live demo)
Or, y'know, use an actual time/date type.

Related

Finding the difference between two times of day

Input prompt asks for a starting time, and then a duration time where it returns two times: one time where they are added, and one where they are subtracted. I've gotten the basics of them, but when I try and do it for certain times (ex: 1:18 and 10:39) I get a negative error:
X Input of 1:18 10:39 : expected [11:57, 2:39] but found [11:57, -9:-21]
Here's the code that does the calculations:
int timeHours, timeMinutes, durHours, durMinutes;
cout << " Time: ";
cin >> timeHours;
cin.get();
cin >> timeMinutes;
cout << " Duration: ";
cin >> durHours;
cin.get();
cin >> durMinutes;
int time, duration, after, before, afterHours, afterMinutes, beforeHours, beforeMinutes;
const int MINUTES_IN_DAY = 60 * 24;
time = (timeHours * 60) + timeMinutes;
duration = (durHours * 60) + durMinutes;
after = time + duration;
before = time - duration;
afterHours = after / 60 % 12;
afterMinutes = after % 60;
beforeHours = before / 60;
beforeMinutes = before % 60;
cout << endl;
cout << durHours << ":" << setfill('0') << setw(2) << durMinutes << " hours after, and before, "
<< timeHours << ":" << timeMinutes << " is [" << afterHours << ":" << setw(2) << afterMinutes << ", "
<< beforeHours << ":" << setw(2) << beforeMinutes << "]" << endl;
The failed test above shows that the sum (1:18 + 10:39) works but the difference (1:18 - 10:39) does not work. It gives me "-9:-21" which should be able to be fixed by adding 24 hours, which is even what my assignment suggests: "This is easily done by adding a day (or two or three) to before when calculating the difference" but when I add 1440 (60 * 24) to the "before" initialization:
before = (time - duration) + MINUTES_IN_DAY;
and convert back from minutes to normal time I get 14:39, which is 2:39, but in 24 hour form, not 12 (incidentally it also makes all the other tests which were passing now failing). I think there's some hint when it says "by adding a day (or two or three) since obviously 1440 is different from 1440*2 or *3, but I'm not seeing it and I have to be missing something obvious. I know I'll have to fix it for midnight as well but I'll change that later. If anyone knows what I'm trying to explain, I'd really appreciate it
Usually, when working with times/dates it's easier to make yourself a function to convert a human-readable date to milliseconds or seconds (and vice versa) and build up from that base. In your case, you'll just add/subtract the two time-marks in seconds for example:
long long time = toSec(timeHours, timeMinutes, timeSeconds);
long long duration = toSec(durHours, durMinutes, durSeconds);
string after = toDate(time + duration);//somethig like 12:34:00 (hh:mm:ss)
string before = toDate(time - duration);
however, putting effort in making such conversion functions would be an overcomplication if all you use them for is a one-time calculation.
( like you suggested to add MINUTES_IN_DAY) to solve the negative values problem you can use the %MINUTES_IN_DAY to avoid the overflow caused by adding MINUTES_IN_DAY to a positive value
before = ((time - duration)+MINUTES_IN_DAY)%MINUTES_IN_DAY;

Wrong result while trying to divide

To learn C++, I follow an online class and I am trying to create a console mode game.
The game take a random word, split the word and ask the user to guess the word.
When the user don't wanna play anymore and quit the game, my program show some statistics (total of game played, game wins ...).
While I am trying to get the win percentage, I get wrong result.
Explanation (What I want) :
My user win 1 game and lose 1 game -> 1/2 * 100 = 50% (win percentage)
What is wrong (What I get) :
My function return 0 for 1/2 * 100.
void gameStatistics(int gameNumber, int gameWin, int defeats, int tries)
{
std::cout << "You quit." << std::endl;
float const winpercentage=float(gameWin / gameNumber) * 100; // C4244, resolved by casting the int into float.
std::cout << "Win average: " << winpercentage << std::endl;
std::cout << "Statistics: Number of games played: " << gameNumber << " Number of win: " << gameWin << " Number of defeat: " << defeats << " Number of tries: " << tries << std::endl;
}
I have been struggling for a while and I need someone to explain what I am doing wrong.
Thanks in advance
1/2 = 0 in integer logic.
1/2.0f = 0.5f in float logic.
This line float(gameWin / gameNumber) means that divide in integer space then convert the result to float space.
You should do this:
float(gameWin) / gameNumber
or even better:
static_cast<float>(gameWin)/ gameNumber
When you do float(gameWin / gameNumber) the division is still an integer division. You need to cast one of the operands as a float, like e.g. float(gameWin) / gameNumber.
Also note that unless you're on a small embedded platform, or writing code to run on a GPU, then there's really no reason to use float these days. Using double is just as "fast" as using float, and double is also the default floating point type (for example when using floating point literals).

Am I doing double to float conversion here

const double dBLEPTable_8_BLKHAR[4096] = {
0.00000000000000000000000000000000,
-0.00000000239150987901837200000000,
-0.00000000956897738824125100000000,
-0.00000002153888378764179400000000,
-0.00000003830892270073604800000000,
-0.00000005988800189093979000000000,
-0.00000008628624126316708500000000,
-0.00000011751498329992671000000000,
-0.00000015358678995269770000000000,
-0.00000019451544774895524000000000,
-0.00000024031597312124120000000000,
-0.00000029100459975062165000000000
}
If I change the double above to float, am I doing incurring conversion cpu cycles when I perform operations on the array contents? Or is the "conversion" sorted out during compile time?
Say, dBLEPTable_8_BLKHAR[1] + dBLEPTable_8_BLKHAR[2] , something simple like this?
On a related note, how many trailing decimal places should a float be able to store?
This is c++.
Any good compiler will convert the initializers during compile time. However, you also asked
am I incurring conversion cpu cycles when I perform operations on the array contents?
and that depends on the code performing the operations. If your expression combines array elements with variables of double type, then the operation will be performed at double precision, and the array elements will be promoted (converted) before the arithmetic takes place.
If you just combine array elements with variables of float type (including other array elements), then the operation is performed on floats and the language doesn't require any promotion (But if your hardware only implements double precision operations, conversion might still be done. Such hardware surely makes the conversions very cheap, though.)
Ben Voigt answer addresses your question for most parts.
But you also ask:
On a related note, how many trailing decimal places should a float be able to store
It depends on the value of the number you are trying to store. For large numbers there is no decimals - in fact the format can't even give you a precise value for the integer part. For instance:
float x = BIG_NUMBER;
float y = x + 1;
if (x == y)
{
// The code get here if BIG_NUMBER is very high!
}
else
{
// The code get here if BIG_NUMBER is no so high!
}
If BIG_NUMBER is 2^23 the next greater number would be (2^23 + 1).
If BIG_NUMBER is 2^24 the next greater number would be (2^24 + 2).
The value (2^24 + 1) can not be stored.
For very small numbers (i.e. close to zero), you will have a lot of decimal places.
Floating point is to be used with great care because they are very imprecise.
http://en.wikipedia.org/wiki/Single-precision_floating-point_format
For small numbers you can experiment with the program below.
Change the exp variable to set the starting point. The program will show you what the step size is for the range and the first four valid numbers.
int main (int argc, char* argv[])
{
int exp = -27; // <--- !!!!!!!!!!!
// Change this to set starting point for the range
// Starting point will be 2 ^ exp
float f;
unsigned int *d = (unsigned int *)&f; // Brute force to set f in binary format
unsigned int e;
cout.precision(100);
// Calculate step size for this range
e = ((127-23) + exp) << 23;
*d = e;
cout << "Step size = " << fixed << f << endl;
cout << "First 4 numbers in range:" << endl;
// Calculate first four valid numbers in this range
e = (127 + exp) << 23;
*d = e | 0x00000000;
cout << hex << "0x" << *d << " = " << fixed << f << endl;
*d = e | 0x00000001;
cout << hex << "0x" << *d << " = " << fixed << f << endl;
*d = e | 0x00000002;
cout << hex << "0x" << *d << " = " << fixed << f << endl;
*d = e | 0x00000003;
cout << hex << "0x" << *d << " = " << fixed << f << endl;
return 0;
}
For exp = -27 the output will be:
Step size = 0.0000000000000008881784197001252323389053344726562500000000000000000000000000000000000000000000000000
First 4 numbers in range:
0x32000000 = 0.0000000074505805969238281250000000000000000000000000000000000000000000000000000000000000000000000000
0x32000001 = 0.0000000074505814851022478251252323389053344726562500000000000000000000000000000000000000000000000000
0x32000002 = 0.0000000074505823732806675252504646778106689453125000000000000000000000000000000000000000000000000000
0x32000003 = 0.0000000074505832614590872253756970167160034179687500000000000000000000000000000000000000000000000000
const double dBLEPTable_8_BLKHAR[4096] = {
If you change the double in that line to float, then one of two things will happen:
At compile time, the compiler will convert the numbers -0.00000000239150987901837200000000 to the float that best represents them, and will then store that data directly into the array.
At runtime, during the program initialization (before main() is called!) the runtime that the compiler generated will fill that array with data of type float.
Either way, once you get to main() and to code that you've written, all of that data will be stored as float variables.

Error multiplying numbers in the trillions

I am trying to perform a calculation to get from the total microseconds of the current time back to the current time in HHMMSSFFF format by performing a series of calculations. However, when I try to subtract the hours*3600000000 from the total number of microseconds, the returned value is not correct (it is off by one order of magnitude and the number itself is wrong. Does anyone know how to fix this? I tried using long long int and long double but these both outputted the same value. I have copied below the code and the resulting output in the console.
The times are stored in a vector as data comes in (aka a time stamp) which is why there is a temp_counter. I am using time_duration in the boost::posix_time library.
long double total = cur_time.at(temp_counter).total_microseconds();
cout << total << endl;
int hours = total/(3600000000);
cout << hours << endl;
long long int temp = hours*3600000000;
cout << std::setprecision(20) << temp << endl;
total = total - temp;
cout << total << endl;
Output:
35465976558
9
2335228928
33130747630
By my calculations, temp should actually be 32400000000 and the new total should be 3065976558.
The calculation is:
35465976558/
3600000000 = 9,851660155 cast to int equals 9
9 * 3600000000 = ... and here the crap hits the fan because 3600000000 cannot be put into a 32 bit int and doesn't seem to be cast correctly to long long, hence you should cast the right hand side to long long int.
But as you are getting a long double in the first assignment: Why not using long double (or at least double) all the way and avoid the casting horror?

How to set 3 digits after comma

Well, basically I was using setprecision(3), but that is rounding up the last number, for example if we do like this -
double x = 5;
x = (double) x / 3;
cout << fixed << setprecision(3) << x << endl;
It will show 1.667
But, if we do it with calculator, it will show - 1.666666666...67
So basically, what I mean is, is there any chance to output in file, just the first 3 digits after the comma, and not to round it up?
1.666666666...67 rounded to three decimal places is 1.667
If you just want to truncate the output then send it to a string with strstream, search the string for the position of "." and truncate the string 3 places beyond that
Or if you simply want to always round down, multiply the result by 1000, use floor() to round down and then divide by 1000.0 again.
A cast to long truncates the fraction part :
int main()
{
double x;
x= -100.666666666666666;
x = static_cast<double> ( static_cast<long>(x * 1000) )/1000;
cout << x << endl;
}
We could use floor(double) from cmath, which is more preferable, but it's rounds negatives to negative side either.
cout << fixed << setprecision(3) << double(int(x*1000))/1000 << endl;
we use int() to truncate the tailing digits.