I have some C++ code that is in this format:
void calculate(int a, float b, long c) {
long long result = (a / b) * (1000 / c);
assert(result > 0);
// more code...
}
However, the assert statement fails. It is a given that a, b, and c are all values that are positive. Then I take it that 'result' ends up becoming 'result == 0' for some reason. Is there something inherent in the logic of the type conversions presented here that is causing my code to fail?
I am new to C++ so the answer may seem obvious...
If c > 1000, then the expression (1000/c) becomes zero due to integer division. Integer division is being performed here because both operands are integral types.
As a result, the expression (a / b) * (1000 / c) becomes zero, so the value of result becomes zero, triggering the assert.
The same thing will happen if b > a, for the same reason as above.
If integer division is not what you want, rewrite your expression like this:
long long result = long long((float(a) / b) * (1000.0f / c));
This invokes floating-point division instead of integer division. The value of a and c will be converted to a floating-point type for the purposes of calculating the result.
Related
Suppose we have three integer (int, long, long long, unsigned int, etc) variables a, b, c. Normally, performing
c = a / b;
would result in truncate of fractions. However, is it possible for c to end up with an incorrect value?
I am not talking about a / b may be out of range for c's type. Rather, I am talking about how integer division is implemented in C. Does performing a / b first generate a float type intermediate result, and then the intermediate value is truncated?
If so, I wonder if loss of precision of the intermediate value can lead to an incorrect value of c. For example, suppose the precise value for a / b is 2, but somehow the intermediate result is 1.9999..., thus c will end up with an incorrect value of 1. Can such cases happen, or does integer division always result in a correct value if the expected value is in the range of c's type?
Does performing a / b first generate a float type intermediate result
As far as the language is concerned, there are no intermediate results.
does integer division always result in a correct value if the expected value is in the range of c's type?
Yes.
Section 6.5.5 of the C11 standards states
When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded. If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a;
Which means there's no way, mathematically, that you'll get wrong results.
Suppose we have three integer (int, long, long long, unsigned int, etc) variables a, b, c. Normally, performing
c = a / b;
would result in truncate of fractions. However, is it possible for c to end up with an incorrect value? I am not talking about a / b may be out of range for c's type.
It should not be possible that for example the last digit of division be wrong, if all rules were followed otherwise. C11 6.5.5p6:
When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded.
i.e. the result is not "close" to but exactly the same as a / b would be algebraically, just anything following the point discarded.
That does not mean there won't be any gotchas: it is possible that the division of a / b might be mathematically not out of range for c's type yet out of range for the type used in the division itself which can cause wrong values be set in c.
Consider this example:
#include <stdio.h>
#include <inttypes.h>
int main(void) {
int32_t a = INT32_MIN;
int32_t b = -1;
int64_t c = a / b;
printf("%" PRId64, c);
}
The result of division of INT32_MIN / -1 is representable in c, it is INT32_MAX + 1, which is positive. However on 32-bit platforms the arithmetic happens in 32 bits, and this division produces an integer overflow which causes the behaviour to be undefined. What happens on my computer is that if I compile without optimizations it aborts the program. If I compile with optimizations enabled (-O3), the compiler will resolve this calculation at compilation time, and handles the overflow in a peculiar way and produces the result -2147483648 which is negative.
Likewise, if you do this:
uint16_t a = 16;
int16_t b = -1;
int32_t result = a / b;
printf("%" PRId32 "\n", result);
the result on a 32-bit int machine is -16. If you change the type of a to uint32_t the math happens in unsigned:
uint32_t a = 16;
int16_t b = -1;
int32_t result = a / b;
printf("%" PRId32 "\n", result);
The result is of course 0. And you would get 0 from the former calculation too on a 16-bit machine.
I am doing something like this
int a = 3;
int b = 4;
float c = a/b ; //This returns 0 while its suppose to return 0.75
I wanted to know why the above code doesn't work ? I realize that 3 is an int and 4 is an int too. However the result is a float which is being assigned to float. However I am getting a 0 here. Any suggestions on what I might be doing wrong ?
The division is evaluated first, and because it is two integer operands, it evaluates to an integer... which then only get assigned to a float.
This is due to a predefined set of rules that decreases in type complexity. To force the result to be of a particular type (at least), at least one of the operands needs to be of that type. (via a static_cast< > )
Thus:
float c = a / static_cast<float>(b);
float c = a/b ;
a and b are integers, so it is integer division.
From the C++ standard:
5.6 Multiplicative operators [expr.mul]
For integral operands the / operator yields the algebraic quotient with any fractional part discarded.
Instaed, try this:
float c = a / static_cast<float>(b);
(As #TrevorHickey suggested, static_cast<float> is better than old-style (float) cast.)
You cant divide two ints and receive a float. You either have to cast to a float or have the types as a float.
float a = 3;
float b = 4;
float c = a/b;
or
float c = (float)a/(float)b;
HINT: the result from integer division is integer. The result of the division is then assigned to a float. That is a/b results in an int. Cast that however you want, but you aren't gonna get 0.75 out of it.
If you are working in C++, you should use the static_cast method over the implicit cast.
This will ensure that the type can be safely cast at compile time.
float c = a/static_cast<float>(b);
int a = 0, b, c, e, n = 25;
e = n;
while(n!=0)
{
n=n/10;
a++;
}
printf("%d",a);
b = e * e;
c = b % (pow(10, a));
if(c==e)
printf("automorphic");
For the line
c=b%(pow(10,a));
the compiler shows an error:
invalid operands of types `int' and `double' to binary `operator%'
pow returns a double, and you can't use % on doubles.
pow returns a double, which you cannot use as operator for the %.
Try:
c=b%((int)pow(10,a));
instead.
As per other answers: pow introduces doubles into your program, and then you hvave to convert them back to ints.
Best to avoid the problem, then:
int a = 1;
while(n!=0)
{
n=n/10;
a *= 10;
}
a /= 10;
b=e*e;
c=b%a;
(Edit) I marked a line "Fishy" because what happens with n=0..9? You probably need
while (n >= 10)
..
(Edit again, sigh) Sorry -- above edit is wrong, you need the total number of digits. a needs adjusting after the loop.
The % operator can be operated only with integers. pow function returns a double and that's why you are getting error.
In C/C++ the modulus operator (%) is limited to integers. You can use fmod (...) for floating-point modulus but you still need to match types to use that. So you are going to have to cast one of your variables or expressions no matter which solution you chose to use; I would use integer modulus personally.
This is in contrast to languages like Java and C#, which allow you to have an integer on one side of the modulus operator and a float on the other with no problems. This can be a source of portability headaches when porting from other languages into C.
The code can be corrected as:
int a = 0, b, c, e, n = 25;
e = n;
while(n!=0)
{
n=n/10;
a++;
}
printf("%d",a);
b = e * e;
/*
call to pow() function returns a double value and b is an integer type variable.
For any operation (here, modular division) the operands must be of same type.
So, the double value returned from call to pow() function must be explicitly
casted to int type as shown in the code below. Also, the first argument to pow()
must to be double (or, float) type. Here, 10 is integer type, correct it as 10.0.
The result will be fine.
*/
c = b % (int)(pow(10.0, a));
if(c==e)
printf("automorphic");
Does the presence of one floating-point data type (e.g. double) ensure that all +, -, *, /, %, etc math operations assume double operands?
If the story is more complicated than that, is there a resource that describes these rules? Should I not ask such questions and always explicitly cast int to double when the result of the equation is double. Here are some equations I'm thinking about. I purposefully did not compile and run then on my system, since this is the type of thing that could be compiler dependent.
int a(1), b(2), c(3);
double d(4.);
double result1 = a + b/d + c; // equal to 4 or to 4.5?
double result2 = (a + b)/d + c; // equal to 3 or to 3.75?
double result3 = a/b + d; // equal to 4 or to 4.5?
I purposefully did not compile and run then on my system, since this is the type of thing that could be compiler dependent.
This is not compiler dependent. C++ clearly defines the order of these operations and how they are converted.
How the conversion happens is dependent on the order of operations.
double result1 = a + b / d + c; // equal to 4 or to 4.5?
In this example, the division happens first. Because this is an int divided by a double, the compiler handles this by converting the int into a double. Thus, the result of b / d is a double.
The next thing that C++ does is add a to the result of b / d. This is an int added to a double, so it converts the int to a double and adds, resulting in a double. The same thing happens with c.
double result3 = a / b + d; // equal to 4 or to 4.5?
In this example, division is handled first. a and b are both ints, so no conversion is done. The result of a / b is of type int and is 0.
Then, the result of this is added to d. This is an int plus a double, so C++ converts the int to a double, and the result is a double.
Even though a double is present in this expression, a / b is evaluated first, and the double means nothing until execution reaches the double. Therefore, integer division occurs.
I find promotion and conversion rules pretty complex. Usually integer-like numbers (short, int, long) are promoted to floating-point equivalents (float, double). But things are complicated by size differences and sign.
See this question for specifics about conversion.
Does one double promote every int in the equation to double?
No. Only the result of a single operation (with respect to precedence).
double result1 = a + b/d + c; // equal to 4 or to 4.5?
4.5.
double result2 = (a + b)/d + c; // equal to 3 or to 3.75?
3.75.
double result3 = a/b + d; // equal to 4 or to 4.5?
4.
You must consider the precedence of every operator, you must think like a parser:
double result1 = a + b/d + c; // equal to 4 or to 4.5?
That's like a + (b/d) +c because the '/' operator has the biggest precedence.Then it doesn't matter what of these 2 operations is made for first, because the floating point operand is in the middle, and it "infects" other operands and make them be double.So it's 4.5.
double result2 = (a + b)/d + c; // equal to 3 or to 3.75?
Same here, it's like ((a+b)/d )+c, so a+b is 3, that 3 becomes a floating point number because gets promoted to double, because is the dividend of d, which is a double, so it's 0.75+3, that is 3.75.
double result3 = a/b + d; // equal to 4 or to 4.5?
It's like (a/b)+d, so a/b is zero and d is 4, so it's 4.
A parser makes all the operations in order of precedence, so you can exactly know what will be the result of the expression.
Generally, if one operand of a binary operator is floating point and the other is integer, the integer is converted to floating point, and the result is floating point.
In a compound expression, with multiple subexpressions, each operator is processed individually, using the precedence rules you probably know. Thus, in a*b + c*d, a*b is evaluated, and c*d is evaluated, and the results are added together. Whatever is in c*d has no effect in a*b and vice-versa.
C++ is complicated, of course, and user-defined operators may have other behaviors.
The authoritative resource that defines the rules is the C++ standard. The standard is quite large and technical. You might prefer to examine the C standard first. See this answer for links to the standards. Any good book on C or C++ should describe the default type conversions and expression evaluation.
I'm trying to avoid long longs and integer overflow in some calculations, so I came up with the function below to calculate (a * b) / c (order is important due to truncating integer division).
unsigned muldiv(unsigned a, unsigned b, unsigned c)
{
return a * (b / c) + (a * (b % c)) / c;
}
Are there any edge cases for which this won't work as expected?
EDITED: This is correct for a superset of values for which the original obvious logic was correct. It still buys you nothing if c > b and possibly in other conditions. Perhaps you know something about your values of c but this may not help as much as you expect. Some combinations of a, b, c will still overflow.
EDIT: Assuming you're avoiding long long for strict C++98 portability reasons, you can get about 52 bits of precision by promoting your unsigned to doubles that happen to have integral values to do the math. Using double math may in fact be faster than doing three integral divisions.
This fails on quite a few cases. The most obvious is when a is large, so a * (b % c) overflows. You might try swapping a and b in that case, but that still fails if a, b, and c are all large. Consider a = b = 2^25-1 and c = 2^24 with a 32 bit unsigned. The correct result is 2^26-4, but both a * (b % c) and b * (a % c) will overflow. Even (a % c) * (b % c) would overflow.
By far the easisest way to solve this in general is to have a widening multiply, so you can get the intermediate product in higher precision. If you don't have that, you need to synthesize it out of smaller multiplies and divides, which is pretty much the same thing as implementing your own biginteger library.
If you can guarentee that c is small enough that (c-1)*(c-1) will not overflow an unsigned, you could use:
unsigned muldiv(unsigned a, unsigned b, unsigned c) {
return (a/c)*(b/c)*c + (a%c)*(b/c) + (a/c)*(b%c) + (a%c)*(b%c)/c;
}
This will actually give you the "correct" answer for ALL a and b -- (a * b)/c % (UINT_MAX+1)
To avoid overflow you have to pre-divide and then post-multiply by some factor.
The best factor to use is c, as long as one (or both) of a and b is greater than c. This is what Chris Dodd's function does. It has a greatest intermediate of ((a % c) * (b % c)), which, as Chris identifies, is less than or equal to ((c-1)*(c-1)).
If you could have a situation where both a and b are less than c, but (a * b) could still overflow, (which might be the case when c approaches the limit of the word size) then the best factor to use is a large power of two, to turn the multiply and divides into shifts. Try shifting by half the word size.
Note that using pre-divide and then post-multiplying is the equivalent of using longer words when you don't have longer words available. Assuming you don't discard the low order bits but just add them as another term, then you are just using several words instead of one larger one.
I'll let you fill the code in.