C++: Simple operator precedence issue or something else? - c++

If I have the following code:
long lSecondsSum = 8039;
double dNumDays = lSecondsSum / (24 * 3600);
I expect to get 0.093044, but for some reason I am getting dNumDays = 0.0000000000.
However, if I write the code as follows:
long lSecondsSum = 8039;
double dNumDays = lSecondsSum/24;
dNumDays = dNumDays/3600;
then I get correct dNumDays = 0.092777777777777778.
How do I avoid all these floating point errors?

lSecondsSum is long, 8039/86400 will be 0
If you convert 24 and 3600 to double, you will get correct result:
double dNumDays = lSecondsSum / (24 * 3600.0);
Or just:
double dNumDays = lSecondsSum / 24.0 / 3600.0;

In your first code snippet you are getting zero because all the math is being done as integers and then converted to double by the assignment. You want to to do all the math in double precision, e.g.
long lSecondsSum = 8039;
double dNumDays = lSecondsSum / (24.0 * 3600.0);
Your second code snippet works because the third line is done in double precision, however the second line is not and you may be expecting it to be, so watch out for that.
The reason for this working like it does is that if you do long * long or long / long then the result will be a long, not a double, even if you assign the resulting long to a double, hence the result of your math was 0. This zero was then assigned to your double. However, long / double will be done in double precision and give you a double back, which is what you want. Essentially, be aware whether your calculations are being done as integer math or in double precision, otherwise you'll get caught out.

Related

Multiply 2 large numbers in C++ have wrong result

There are 2 large integer numbers. When I multiply it the result is always wrong, even if I used long double and the result should be in valid range of long double:
long double f = 1000000000 * 99999;
I debugged, and the result is so strange: -723552768.00000000. Did I missed something? how can I multiple it?
Thanks and regard!
from the C++ standards:
4 An unsuffixed floating constant has type double. If suffixed by the
letter f or F, it has type float. If suffixed by the letter l or L, it
has type long double
auto fl = 1000000000.L * 99999.L;
std::cout << fl << "\n";
or
long double fl = 1000000000L * 99999.L;
std::cout <<"\n"<< fl << "\n";
Numeric literals are int by default in C++. Thus, the expression 1000000000 * 99999 is viewed as the multiplication of two int 's and therefore the result returned by the * operator is an int. This int is only converted to the long double variable f after the multiplication has taken place. Depending on your platform, the range of int is usually from -2147483648 to 2147483647 (or 4 bytes in size). However, the product of 1000000000 x 99999 is 9.9999 x 10^13 which falls outside this range and thus overflow occurs as the int variable is not large enough to hold the value.
To avoid this, at least one of the numbers the * operator operates on should be declared as a long double literal with the suffix .l or .L as follows:
long double f = 1000000000.L * 99999
In the above expression , the * operator will return a long double which is large enough to hold the resulting product before being assigned to f.
Agree with #feiXiang. You are basically multiplying two ints. To do correct calculations, you have to define large numbers as long double. See the code below:
#include <iostream>
using namespace std;
int main()
{
long double a = 1000000000;
long double b = 99999;
long double f = a * b;
cout<<f;
return 0;
}
Output:
9.9999e+13
Actually you invoke undefined behavior with:
long double f = 1000000000 * 99999;
First, evaluate 1000000000 * 99999, which is a multiplication of two int objects. Multiplying two int objects is always an int. Since int is not big enough to represent the result (most likely 32 bits), the upper bits are lost.
Since overflows in signed integer types is undefined, you just triggered undefined behavior. But in this case it is possible to explain what happened, even though it is UB.
The computation keeps only the lowest 32 bits, which should be (1000000000 * 99999) modulo (2**32) == 3571414528. But this value is too big for int. Since on PC int negatives are represented by two's complement, we have to subtract 2**32, every time 2**31<= result < 2**32. This gives -723552768
Now, the last step is:
long double f = -723552768
And that is what you see.
To overcome the issue, either use long long like this:
long double f = 1000000000LL * 99999;
Or double:
long double f = 1000000000.0 * 99999;
1000000000 and 99999 are integer numbers, then the result of 1000000000 * 99999 will be an integer before it is assigned to your variable, and the result is out of range of integer.
You should make sure that the result is a long double first:
long double f = (long double) 1000000000 * 99999;
Or
long double f = 1000000000LL * 99999;

appending anything but a string to std::stringstream returns 0

Code in question:
std::stringstream cd;
int f = int((15 / allyCounter) * 100);
cd << f;
allyCounter is equal to 45. the idea is to get what percentage 15 is of allyCounter where allyCounter is a dynamic int that is constantly changing. i don't have much experience with c++ so I'm sure what I'm missing is something fundamental.
The problem here is almost certainly with integer vs. floating point math.
15/45 (when done in integer math) is 0.
Try
std::stringstream cd;
int f = int((15.0 / allyCounter) * 100);
cd << f;
...and see if things aren't better. 15.0 is a double precision floating point constant, so that'll force the math to be done in floating point instead of integers, so you'll get a percentage.
Another possibility would be to do the multiplication ahead of the division:
int f = 1500 / allyCounter;
If the numerator were a variable, this could lead to a problem from the numerator overflowing, but in this case we know it's a value that can't overflow.
In C++, 15 / 45 is 0. (It's called "integer division": the result of dividing two ints in C++ is also an int, and thus the real answer is truncated, and 15 / 45 is 0.)
If this is your issue, just make it a double before doing the division:
int f = static_cast<double>(15) / allyCounter * 100;
or even:
int f = 15. / allyCounter * 100;
(The . in 15. causes that to be a double.)
You are using integer division:
std::stringstream cd;
int f = int((15.0 / allyCounter) * 100);
cd << f;
The compiler sees 15/allyCounter and thinks it should return an integer (you passed it two integers, right?). 15/150 == 0 with integer division, you always round down. In this case the compiler sees 15.0 as a double, and uses decimal places.

Problems while dividing by 100 [duplicate]

This question already has answers here:
Division in C++ not working as expected
(6 answers)
Closed 8 years ago.
Helo, I'm new to programming and run into an issue, I have an integer, for example 158, and I divide it by 100 that i get is 1, but I want 1.58 instead
It is probably known issue, but sorry, I'm noob, for now :)
Just cast this to float number
int i = 158;
float f = (float)i / 100; //less precision
double d = (double)i / 100; //more precision
//other way
int i = 158;
float f = i / 100.0; //less precision
double d = i / 100.0; //more precision
What you are doing is dividing integer from integer, in this case result always integer, to get floating point number at least one of two operand has to be floating point number.
You need to divide by 100.0 rather than 100
Dividing by an integer in C++ is always going to give you an integer, so it will never be completely accurate. That being said, it was mentioned above that you can divide by a double or long to get the accurate decimal number that you desire.

Not getting expected results with pow() in C++

I am doing a homework assignment for my C++ class, and am trying to do what I consider a fairly simple math function, but I'm getting stumped because it is not returning what I expect it to return. Basically, it's just an APR problem and I am trying to convert from APR to monthly interest. My instructor has given us this formula to calculate this:
monthlyInterest = ((APR / 100) + 1)^(1/12)
So this is the code I am using. I separated yearlyInterest from the monthlyInterest calculation because I was making sure I wasn't making a simple mistake:
double balance, payment, APR;
cin >> balance >> payment >> APR;
const double yearlyInterest = (APR / 100) + 1;
const double monthlyInterest = pow(yearlyInterest, 1/12)
Using the inputs 1000, 100, and 19.9, the results I get in my physical calculator, and what I am expecting are:
yearlyInterest ~1.19
monthlyInterest ~1.015...
But the result my debugger is giving me is:
yearlyInterest ~1.19
monthlyInterest = 1
So basically, I am asking why my monthlyInterest is incorrect? I don't believe it is a type issue because pow() will output a double. Also, I don't think that the decimal should overflow the double type, it's not that big and I only need a few digits of accuracy anyway. So if anyone can help me determine the mistake I made, I would appreciate it.
Sidenote: I have included the following. I use instead of because it is what I learned on. If this is a problem, I can change it.
#include <iostream>
#include <cmath>
In this line:
const double monthlyInterest = pow(yearlyInterest, 1/12)
1/12 gets rounded to 0 (because it's integer division) and the result is 1. Replace with:
const double monthlyInterest = pow(yearlyInterest, 1.0/12)
Mind the ..
1/12 and APR are performing integer division.
If you explicitly use floating point numbers you'll get your expected results.
Instead of 1/12 use 1/12. (notice decimal point)
and instead of APR/100 use APR/100. (notice decimal point)
One thing is clear and that is that 1/12 == 0 (try 1./12).
Danger, Will Robinson! 1/12 is not the same as 1.0/12.0.
You need to make the expression 1/12 return a float value to force floating point division instead of integer division.
change:
const double monthlyInterest = pow(yearlyInterest, 1/12);
to:
const double monthlyInterest = pow(yearlyInterest, 1.0/12);
const double monthlyInterest = pow(yearlyInterest, 1/12);
integer division of 1/12 truncates the fractional result to 0. Thus the above line would be processed as
const double monthlyInterest = pow(yearlyInterest, 0);
and a number raised to the 0 power equals 1. Thus in your case monthlyInterest is assigned the value 1.

There are possible way of dividing two float numbers which was casted from unsigned int make negative float result?

unsigned int deltaTime = now() - last();
unsigned int freq = getFreq();
float timeOfGap = float(deltaTime) / float(freq);
ASSERT(0.0f <= timeOfGap, "WHAT?");
I got a really weired result from my program. I didn't catch a scene which is happened. But I have a log which said that really raised at least multiple times.
There are possible way of dividing between two float numbers which was casted from unsigned int make negative float result?
OK, thank you guys. I'm glad to see your attentions.
Let me try to add some descriptions about it. It'll be helpful for you.
I'm working for an online game, and this situation was raised rarely but frequently while hundreds of million times game was serving. I can't debug or catch the exact shot, but it is logged on the db error messages.
The timeOfGap should be NaN as you noticed, but the log didn't alert the value exactly. The timeOfGap is accumulated like below;
mTotalFrameRateTimeAsASecond += timeOfGap;
And this program logs mTotalFrameRateTimeAsASecond, that was a negative value. But except this sign of value was a negative, it is correct value. Meaning, it point time as look as good if I divide the final value with a framerate. A hypothetical play time was 500 sec, it is -30000(with 60 framerate per sec).
Maybe it is not negative, but a NAN. 0.0f <= NAN is false. It may happen if both operands are zero.
This should find the problem:
unsigned int deltaTime = now() - last();
unsigned int freq = getFreq();
float timeOfGap = float(deltaTime) / float(freq);
char s[50] ;
sprintf (s, "WHAT? %u/%u < 0!", deltaTime, freq);
ASSERT(0.0f <= timeOfGap, s);
The value nan will not compare to anything successfully. So if you have:
float f = 0.0 / 0.0;
assert(f > 0 || f <= 0);
The assertion will fail!
You can do a simple test to verify the cast from unsigned int to float.
Try this :
unsigned int toto = 0xFFFFFFFF;
float convertedToto = float(toto);
convertedToto will equals -1 if the convertion (unsigned int -> float) is in fact (int -> float). You should get 2*10e31 with a proper conversion.