Error multiplying numbers in the trillions - c++

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?

Related

Program accuracy varying by parameters

I am trying to learn how to program in C++, so I created something that allowed to you enter a minimum, and maximum parameter, and it will compute k+(k+1)+(k+2)+...+(max), and compared it to the analytical value, using the standard formula (n(n+1)/2). It seems to work fine when I try small numbers, but when, for example, trying min=4, max=4*10^5 (400,000), I get a negative result for the sum, but a positive result checking with the analytical method, even after changing the type from 'int' to 'long'. Trying other combinations, I have achieved the opposite, with the analytical method resulting in a negative sum. I suspect this is related to the fact the type int can go up to a certain number of digits, but I wanted some confirmation on that, and if it isn't, what the actual problem is. The code is provided below:
#include <iostream>
// Values are inconsistent when paramin,parammax become large.
// For example, try (parammin,parammax)=(4,400,000)
int main() {
int parammax,parammin;
std::cout << "Input a minimum, then maximum parameter to sum up to" << std::endl;
std::cin >> parammin >> parammax;
int sum=0;
for (int iter = parammin; iter <= parammax; iter++){
sum += iter;
}
std::cout << "The sum is: " << sum << std::endl;
const int analyticalmethod = (parammax*(parammax+1)-parammin*(parammin-1))/2;
std::cout << "The analytical result for the sum is,"
" via (max*(max+1)-min*(min-1))/2: "
<< analyticalmethod << std::endl;
return 0;
}
Using very large numbers without control is dangerous in C++. The basic types int, long and long long are implementation dependant, with only the following requirements:
int is at least 16 bits large
long is at least as large as int and at least 32 bits large
long long is at least as large as long and at least 64 bits large
If you think you can need larger values, you should considere a multi precision library like the excellent gmp.

C++ series summation code giving different answers on large input

I am adding numbers from 1 to n in C++. I have used both the iteration method and mathematical formula. The code works fine for up to 9 digits.
But when I give input a 10 digit number, the formula and iteration methods give separate answers.
I have tried to look it up on google but couldn't find any solution for this. My code:
#include <bits/stdc++.h>
using namespace std;
int main(){
unsigned long long i, n, sum = 0, out_put;
cout << "Sum of numbers from 1 to: ";
cin >> n;
/// using mathematical formula
out_put = n*(n+1);
out_put = out_put/2;
cout << " = " << out_put << endl;
/// using iteration
for (i=1; i<=n; i++){
sum = sum+i;
}
cout << " == " << sum << endl;
return 0;
}
How do know which one is the correct one? If I assume the formula can't be wrong then why is the iteration method giving incorrect answer? I have used unsigned long long to prevent overflow but still didn't work.
What you are seeing is overflow happening on your calculations at different points. 9,999,999,999 * 10,000,000,000 is ~9.9e19 while an unsigned long long holds ~1.8e19. So the result wraps around and you get one answer.
Your for loop is also going to overflow but it is going to do so at a different point meaning the answers will diverge from one another since the modulo arithmetic is happening with a smaller number.
Your problem is that n*(n+1) can be too large to store in an unsigned long long, even though the end result (half of that) which you calculate via iteration may still fit.
Assuming your unsigned long long has 64 bits, it can hold integers up to 18446744073709551615. Anything above that will restart from 0.
Edit: As Nathan points out, you can of course have both calculations overflow. The sum would still give the correct result modulo 2^64, but the direct calculation can be off because the division does not generally yield the same result modulo 2^64 after you have wrapped around.
#include <bits/stdc++.h>
using namespace std;
int main(){
unsigned long long i, n, sum = 0, out_put;
cout << "Sum of numbers from 1 to: ";
cin >> n;
/// using mathematical formula
out_put = n*(n+1);
out_put = out_put/2;
cout << " = " << out_put << endl;
/// using iteration
for (i=1; i<=n; i++){
sum = sum+i;
}
cout << " == " << sum << endl;
return 0;
}

Program to calculate age in seconds not working correctly

I am attempting to create a simple program that calculates a users age in seconds after they give their age in years. It works fine for ages 0-68 but any age of 69 or higher breaks the program and just spits out the same wrong number every time. The program is listed below and any help would be appreciated.
#include <iostream>
using namespace std;
int main()
{
int age;
cout << "Please enter your age in years ";
cin >> age; //Grabs the users age
unsigned long long int result = age*365*24*60*60; //calculates the users age in seconds
cout << "Your age in seconds is: " << result << " seconds";
return 0;
}
The way C++ works here is basically:
int temp = age*365*24*60*60;
unsigned long long int result = static_cast<unsigned long long>(temp);
So, you can probably see that the expression will overflow an int at around 69 years old (on your architecture). So, you want to force the calculation to work in unsigned long long, so the easiest way is to force one of the values to be unsigned long long, which will make the expression also unsigned long long. For example:
unsigned long long int result = age*365ULL*24*60*60; //calculates the users age in seconds
// ^^^ declare constant as type unsigned long long
Unsigned Long int ranges from -2,147,483,648 to 2,147,483,647
So for any value less than or equal to 68, age in seconds is 2,144,448,000 or less which falls within range.
However for Age 69, Age in seconds comes out to be 2,175,984,000 which overflows the range.
I advise using long Double.

How can you switch a float to a time format?

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.

Euler's number expansion

#include <iostream>
#include <iomanip>
using namespace std;
int a[8], e[8];
void term (int n)
{
a[0]=1;
for (int i=0; i<8; i++)
{
if (i<7)
{
a[i+1]+=(a[i]%n)*100000;
}
/* else
{
a[i+1]+=((a[i]/640)%(n/640))*100000;
}
*/
a[i]=a[i]/(n);
}
}
void sum ()
{
}
int factorial(int x, int result = 1)
{
if (x == 1)
return result;
else return factorial(x - 1, x * result);
}
int main()
{
int n=1;
for (int i=1; i<=30; i++)
{
term(n);
cout << a[0] << " "<< a[1] << " " << a[2] << " "
<< a[3] << " " << a[4] << " " << a[5]<< " "
<< " " << a[6] << " " << a[7] << endl;
n++;
for (int j=1; j<8; j++)
a[j]=0;
}
return 0;
}
That what I have above is the code that I have thus far.
the Sum and the rest are left purposely uncompleted because that is still in the building phase.
Now, I need to make an expansion of euler' number,
This is supposed to make you use series like x[n] in order to divide a result into multiple parts and use functions to calculate the results and such.
According to it,
I need to find the specific part of the Maclaurin's Expansion and calculate it.
So the X in e=1+x+(1/2!)*x and so on is always 1
Giving us e=1+1+1/2!+1/3!+1/n! to calculate
The program should calculate it in order of the N
so If N is 1 it will calculate only the corresponding factorial division part;
meaning that one part of the variable will hold the result of the calculation which will be x=1.00000000~ and the other will hold the actual sum up until now which is e=2.000000~
For N=2
x=1/2!, e=previous e+x
for N=3
x=1/3!, e=previous e+x
The maximum number of N is 29
each time the result is calculated, it needs to hold all the numbers after the dot into separate variables like x[1] x[2] x[3] until all the 30~35 digits of precision are filled with them.
so when printing out, in the case of N=2
x[0].x[1]x[2]x[3]~
should come out as
0.50000000000000000000
where x[0] should hold the value above the dot and x[1~3] would be holding the rest in 5 digits each.
Well yeah Sorry if my explanation sucks but This is what its asking.
All the arrays must be in Int and I cannot use others
And I cant use bigint as it defeats the purpose
The other problem I have is, while doing the operations, it goes well till the 7th.
Starting from the 8th and so on It wont continue without giving me negative numbers.
for N=8
It should be 00002480158730158730158730.
Instead I get 00002 48015 -19220 -41904 30331 53015 -19220
That is obviously due to int's limit and since at that part it does
1936000000%40320
in order to get a[3]'s value which then is 35200 which is then multiplied by 100000
giving us a 3520000000/40320, though the value of a[3] exceeds the limit of integer, any way to fix this?
I cannot use doubles or Bigints for this so if anyone has a workaround for this, it would be appreciated.
You cannot use floating point or bigint, but what about other compiler intrinsic integral types like long long, unsigned long long, etc.? To make it explicit you could use <stdint.h>'s int64_t and uint64_t (or <cstdint>'s std::int64_t and std::uint64_t, though this header is not officially standard yet but is supported on many compilers).
I don't know if this is of any use, but you can find the code I wrote to calculate Euler's number here: http://41j.com/blog/2011/10/program-for-calculating-e/
32bit int limits fact to 11!
so you have to store all the above facts divided by some number
12!/10000
13!/10000
when it does not fit anymore use 10000^2 and so on
when using the division result is just shifted to next four decimals ... (as i assumed was firstly intended)
of course you do not divide 1/n!
on integers that will be zero instead divide 10000
but that limits the n! to only 9999 so if you want more add zeroes everywhere and the result are decimals
also i think there can be some overflow so you should also carry on to upper digits