casting integer division into double in C - c

Why does the code
double slope = (double)changeY/changeZ
set slope to 0.0, when in the program I have, changeX = 20 and changeY = 10 (both ints)?

It sounds like you are using the wrong variable. Try this:
int changeX = 20;
int changeY = 10;
double slope = (double)changeY/changeX;
The cast operator () has higher priority than /. This expression will get evaluated as:
Cast changeY to a double.
Implicitly convert changeX to a double. If one operand is double, then the other operand gets balanced to a double as well (this is formally called "the usual arithmetic conversions").
Divide the two operands. The result will be a double.
Store this temporary "result-double" into another double called slope.

Related

How to print a double data type in C [duplicate]

This question already has answers here:
How to divide 2 int in c?
(5 answers)
C - double result returning the value of 0 [duplicate]
(2 answers)
Closed 4 years ago.
Why in C, when I print a double type variable with %f it shows 8.000000… but that is not the desire result . i want a result like 8.5000 how can i achieve this?
int main(){
int i, j;
double k;
i=8; j=9;
k = (i+j)/2;
printf("%f", k);
}
The problem is not with the format specifier, rather with the arithmatic operation.
By saying
k = (i+j)/2;
where, i and j and 2 - all are ints, you're doing integer division, and then, storing the result in a double. For integer division,
[..] When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded [...]
which is commonly known as "truncation towards zero". To avoid that from happenning, you need to enforce floating point arithmetic, by forcing or casting one of the operands to double (or float). Something like
k = ((double)i+j)/2;
or,
k = (i+j)/2.0; //2.0 is of type double
The point here is, if, in the operation, one of the operands is of the higher rank (double or float is higher ranked that int), all the operands will first be converted to the higher rank, and then the operation will be performed and the result will be of the type of the higher ranked type.
Since i and j are int the result is cast first to int. This looses precision. Explicitly cast to double k = (double)(i+j)/2
Comments are right. To better understand that: A C expression is evaluated in 'one chunk'. The right side of your assignment (i+j)/2 is a complete expression. Since it does only includes integer values, the arithmetic chosen will also be of integer type, (which leads to truncation of the result), creating temporary integer value (invisible to you), which is then assigned to a double.
You need to make at least one of the values in your expression a double (or float), then the compiler will promote all the arithmetic to floating point and the temporary value will also be of float type.
If you don't have a constant in your expression, you can also use casts:
((float)i+J)/2
It does not matter which of the 3 items get the cast, just one is enough.

Can a int value added to a float value?

/**Program for internal typecasting of the compiler**/
#include<stdio.h>
int main(void)
{
float b = 0;
// The Second operand is a integer value which gets added to first operand
// which is of float type. Will the second operand be typecasted to float?
b = (float)15/2 + 15/2;
printf("b is %f\n",b);
return 0;
}
OUTPUT : b is 14.500000
Yes, an integral value can be added to a float value.
The basic math operations (+, -, *, /), when given an operand of type float and int, the int is converted to float first.
So 15.0f + 2 will convert 2 to float (i.e. to 2.0f) and the result is 17.0f.
In your expression (float)15/2 + 15/2, since / has higher precedence than +, the effect will the same as computing ((float)15/2) + (15/2).
(float)15/2 explicitly converts 15 to float and therefore implicitly converts 2 to float, yielding the final result of division as 7.5f.
However, 15/2 does an integer division, so produces the result 7 (there is no implicit conversion to float here).
Since (float)15/2 has been computed as a float, the value 7 is then converted to float before addition. The result will therefore be 14.5f.
Note: floating point types are also characterised by finite precision and rounding error that affects operations. I've ignored that in the above (and it is unlikely to have a notable effect with the particular example anyway).
Note 2: Old versions of C (before the C89/90 standard) actually converted float operands to double in expressions (and therefore had to convert values of type double back to float, when storing the result in a variable of type float). Thankfully the C89/90 standard fixed that.
Rule of thumb: When doing an arithmetic calculation between two different built-in types, the "smaller" type will be converted into the "larger" type.
double > float > long long(C99) > long > short > char.
b = (float)15/2 + 15/2;
Here the first part, (float)15/2 is equivalent to 15.0f / 2. Because an operation involving a "larger" type and a "smaller" type will yield a result in the "larger" type, (float)15/2 is 7.500000, or 7.5f.
When it comes to 15/2, since both operands are integers, the operation is done only on integer level. Therefore the decimal point is stripped (from int), and only gives 7 as a result.
So the expression is calculated into
b = 7.5f + 7;
No doubt you'll have 14.500000 as the final result, because it's exactly 14.5f.
b = (float)15/2 + 15/2;
The first one((float)15/2) will work fine. The second one will also work but will be converted into an integer first, so you will lose precision. Like:
b = (float)15/2 + 15/2;
b = 7.500000f + 7
b = 14.500000
It's worth asking: if an integer value could not be added to floating-point value, what would the symptom be?
Compiler issues error or warning message.
Something gets truncated; you don't get the result you want.
Undefined behavior: you might or might not get the result you want, and the compiler might or might not warn you about it.
But in fact none of these things happen. When you add an integer to a floating-point value, the compiler automatically converts the integer to a floating-point value so it can do the addition that way, and this is perfectly well defined. For example, if you have the code
double d = 7.5;
int i = 7;
double result = d + i;
the compiler interprets this just as if you had written
double result = d + (double)i;
And it works this way for just about all operations: the same logic is applied when you subtract, multiply, or divide a floating-point value and an integer.
And it works this way for just about all types. If you add a long int and an int, the plain int automatically gets converted to a long.
As a general rule (and I really can't think of too many exceptions), the compiler always wants to do arithmetic on two values of the same type. So whenever you have two values of different type, the compiler will just about always convert one of them for you. The full set of rules for how it does this are rather elaborate, but they're all supposed to make sense, and do what you want. The full set of rules is called the usual arithmetic conversions, and if you do a Google search on that phrase you'll find lots of explanations.
One case that does not necessarily do what you want is when the two variables are not different types. In particular, if the two variables are both integers, and the operation you're doing is division, the compiler doesn't have to convert anything: it divides the integer by the integer, discarding any remainder, and gives you an integer result. So if you have
int i = 1;
int j = 2;
int k = i / j;
then k ends up containing 0. And if you have
double d = i / j;
then d ends up containing 0 also, because the compiler follows exactly the same rules when performing the division; it doesn't "peek outside" to see that it's going to need a floating-point result.
P.S. I said, "As a general rule, the compiler always wants to do arithmetic on two values of the same type", and I said I couldn't think of too many exceptions. But if you're curious, two exceptions are the << and >> operators. If you have x << y, where x is a long int and y is a plain int, the compiler does not have to convert y to a long int first.

Trying to print answer to equation and getting zero in C.

printf("Percent decrease: ");
printf("%.2f", (float)((orgChar-codeChar)/orgChar));
I'm using this statement to print some results to my command console, however, I end up with zero. Putting the equation into another variable doesn't work either.
orgChar = 91 and codeChar = 13, how do I print out this equation?
Integer division will lead to result 0 here and you are type casting the result later to float so eventually you will end up with 0
Make any one of the variables float before division
(orgChar-codeChar)/(float)orgChar
As others have mentioned, the subtraction and division are done using integer math before the cast to (float). By that point, the integer division has a truncated result of 0. Instead:
// (float)((orgChar-codeChar)/orgChar)
((float) orgChar - codeChar)/orgChar
// or
(orgChar - codeChar)/ (float) orgChar
As the float argument gets converted to double as part of the "usual argument promotion" of arguments to a variadic function like printf(), might as well do
printf("%.2f", (orgChar-codeChar)/ (double) orgChar);
Casting, in general, should be avoided. Some casts unintentionally narrow the operation. If unsigned is 32-bit and a1 is uint64_t, then a1 was narrowed before the shift and unexpected results may occur. If a1 was a char, it is nicely converted without trouble to an unsigned.
The second method of *1u will not narrow. It will insure a2*1u is at least the width of an unsigned.
unsigned sh1 = (unsigned) a1 >> b1; // avoid
unsigned sh2 = a2*1u >> b2; // better
So recommend, rather than (float) or (double), use the idiom of multiplying by 1.
printf("%.2f", (orgChar - codeChar) * 1.0 / orgChar);
you don't need to typecast the whole expression. you can simply type cast either the numerator or the denominator to get the float result with precision of 2 decimal places.
for eg:
here in this code defining a variable c as float doesnt guarantee the result to be float.for getting the precise result you need to typecast either the numerator or denominator.
You shouldn't need to cast to float at all. Simply make sure both variables are of type float or double before attempting to print them as floats. This means either declaring the variables as floats, or using the correct function, such as atof () when converting the data to floats (normally this is done when you get the data from the command-line or a file.)
This should work...
#include <stdio.h>
int
main (void)
{
float orgChar = 91;
float codeChar = 13;
printf ("%.2f\n", (orgChar - codeChar) / orgChar);
return 0;
}

Why do we separately cast to "float" in an integer division?

For example:
int number1 = 1, number2= 2;
float variable = (float)number1/(float)number2;
Instead of this, Why can't we use "float" only once? For example:
int number1 = 1, number2= 2;
float variable = (float)(number1/number2);
The objective is to avoid the truncation that comes with integer division. This requires that at least one of the operands of the division be a floating point number. Thus you only need one cast to float, but in the right place. For example,
float variable = number1/(float)number2; // denominator is float
or
float variable = ((float)number1)/number2; // numerator is float
Note that in the second example, one extra set of parentheses has been added for clarity, but due to precedence rules, it is the same as
float variable = (float)number1/number2; // numerator is float, same as above
Also note that in your second example,
float variable = (float)(number1/number2);
the cast to float is applied after the integer division, so this does not avoid truncation. Since the result of the expression is assigned to a float anyway, it is the exact of
float variable = number1/number2;
You can write either expression, but you get different results.
With float variable = (float)(number1 / number2); the value in variable is 0, because the division is done as integer division, and 1/2 is 0, and the result is converted.
With float variable = (float)number1 / (float)number2;, the value in variable is 0.5, because the division is done as floating point division.
Either one of the casts in float variable = (float)number1 / (float)number2; can be omitted and the result is the same; the other operand is converted from int to float before the division occurs.
Since number1 and number2 are ints, the division performed will be integral division. Thus, number1/number2 will evaluate to the int 0. To do floating point arithmetic instead, you need to cast them. Note that simply casting one will suffice, since the other one will be implicitly promoted. So, you can just say ((float)number1)/number2.
In the First case,
1/2 results 0
In the second case, you can use float once, but it has to be applied with one of the numbers before division
1.0/2.0 or 1.0/2 or 1/2.0 results 0.5

correct C casts

I'm not so sure about correct casts, here especially from unsigned int and #defines (whatever type that is) to double.
In this example
#define SPEEDSENSOR_EDGES_NUM 10
int speed_counter_left;
double result = speed_counter_left / SPEEDSENSOR_EDGES_NUM;
the result always is 0 when speed_counter_left is < 10.
So I put in some casts:
double result = (double) ((double) speed_counter_left / (double) SPEEDSENSOR_EDGES_NUM);
This is correct, but I think there are too many casts. How can I figure out the correct way with least casts?
Having one double operand should be enough:
double result = (double)speed_counter_left / SPEEDSENSOR_EDGES_NUM;
The cast "sticks" closest to speed_counter_left. So it's essentially equivalent to:
double result = ((double)speed_counter_left) / SPEEDSENSOR_EDGES_NUM;
and #defines (whatever type that is) to double.
The standard says:
6.4.4.1 - 5
The type of an integer constant is the first of the corresponding list
in which its value can be represented.
And (for decimal constants without suffixes) the list goes: int, long int, long long int.
No need to cast, make SPEEDSENSOR_EDGES_NUM a double by using 10.0 instead of 10.
#define SPEEDSENSOR_EDGES_NUM 10.0
int speed_counter_left;
double result = speed_counter_left / SPEEDSENSOR_EDGES_NUM;

Resources