Understanding double and integers - c

Absolute beginner programmer and wondered if you could help me understand some results and terms. I'm trying to follow the programs logic and how it works out certain values. The following case is an example to try and understand these concepts.
#include <stdio.h>
void main ()
{
int inum = 11;
double dnum = 2.56;
double dec_result;
int int_result;
dec_result = inum / 4 + (3.0 * inum) / 5;
printf("value in dec_result is %.2f\n", dec_result);
dec_result = (double) inum / 4 + (3 * inum) / 5;
printf("value in dec_result is %.2f\n", dec_result);
int_result = (int) dnum * 10 + 1;
printf("value in int_result is %d\n", int_result);
int_result = (int) (dnum * 10 + 1);
printf("value in int_result is %d\n", int_result);
}
I know the results as I've run it through Visual Basic. What I'm struggling to follow is how it works it out.
My workings:
inum and dnum I presume are 'names for values' and could be used interchangeably with say x or y. Same with int_result and dec_result.
First dec_result is 8.60
dec_result = inum / 4 + (3.0 * inum) / 5;
11 (an integer) / 4 + (3.0 * 11) / 5
11 (an integer) / 4 + (33.0) / 5
Then I'm a bit lost... 2.75 + 6.6?
Somehow, due to inum being an integer, value is truncated if written as fraction. But as remaining inum in the brackets is multiplied first then it becomes a decimal place number?
It's displayed as decimal places as specified by the placeholder and specified by data type double.
Second dec_result is 8.75
dec_result = (double) inum / 4 + ( 3 * inum) / 5;
= as double is a cast operator you change inum from int to double, so therefore:
= (double) inum / 4 + (33) / 5;
Then = inum/4 becomes 2.75 + 33/5
Why does the 33/5 bit become 6?
It's displayed as decimal places as specified by the placeholder and specified by data type double.
int_result = (int) dnum * 10 + 1;
= cast operator alters dnum a double to integer so 2.56 becomes 2
= 2 * 10 + 1
= 20 + 1
= 21
should be an integer as specified before the bracket and also %d placeholder means to provide the value as number with no decimal point.
int_result = (int) (dnum * 10 + 1);
I got:
= (int) (2.56 * 10 + 1)
= (int) (25.6 + 1)
= (int) (26.6)
= 26
because the value should be an integer as specified before the bracket and also %d placeholder means to provide the value as number with no decimal point.
Is my logic correct?

The C compiler will do integer arithmetic only if both operands are integers (integer / integer, integer + integer, etc.), otherwise it will do floating point arithmetic (double / integer, double + integer, etc.)
First result:
11 (an integer) / 4 + (33.0) / 5
The first part (11/4) is computed with integer arithmetic, so the answer is 2
The second part (33.0 / 5) is computed with floating point arithmetic, so the answer is 6.6 and the sum is 8.6
Second result:
(double) inum / 4 + (33) / 5;
"(double) inum / 4" is computed using floating point arithmetic, so the answer is 2.75.
"33 / 5" is computed using integer arithmetic, so the answer is 6, and the sum is 8.75
In the following:
int_result = (int) dnum * 10 + 1;
The variable dnum is first cast to an integer, so integer arithmetic is used: 2 * 10 + 1 == 21
And finally:
int_result = (int) (dnum * 10 + 1);
In this case, "dnum * 10 + 1" is computed first, which is done using floating point arithmetic: 2.56 * 10 + 1 == 26.6. Then the cast - (int) - truncates to give 26.

When an arithmetic operator is given two integer arguments, the result is an integers, so any fraction is discarded. So11 / 4is2, not2.75`. But when you combine an integer with a floating point, the integer is first converted to floating point, and a floating point result is returned.
As a result:
dec_result = inum / 4 + (3.0 * inum) / 5;
= 11 / 4 + (3.0 * 11) / 5
= 11 / 4 + (3.0 * 11.0) / 5
= 2 + 33.0 / 5
= 2 + 6.6
= 8.6

Related

Math operation doesn't return expected result

I'm using a function, but the code will not work. I broke the function down into its parts and tried to understand what's going on myself. I got this:
int res;
res = (1 / 2) * 2 + 2;
printf("%d", res);
Calculating myself:
(1 /2) = 0.5
0.5 * 2 = 1
1 + 2 = 3
(1 / 2) * 2 + 2 = 3, right?
However, when I run the code it gives me an output of '2', instead of '3'.
When I try this: (making '(1 / 2)' to '0.5')
int res;
res = 0.5 * 2 + 2;
printf("%d", res);
I get an expected output of '3', which is weird because the example above is theoretically the same as the lower one. Does it have to do with my compiler not knowing simple math prioritising rules?
1/2 actually tries to return an integer result (0), which multiplied by 2 is also 0.
You can try typecasting it
float res;
res = (float)1/(float)2 * 2 + 2;
printf("%f", res);
It will force the result to be a float result (0.5), which will lead to the correct answer

Casting double to int works with constants only

I found a strange (to me) behavior of casting to int in C. Appologies if that's a basic question but I'm unable to find the answer to why the following code produces an unexpected result.
#include <stdio.h>
int main(void)
{
printf("1000 * 0.1 = %d\n", (1000 * 0.1));
printf("1000 * (10/100) = %d\n", (1000 * (10/100)));
printf("(int)1000 * 0.1 = %d\n", (int)(1000 * 0.1));
printf("(int)1000 * (10/100) = %d\n", (int)(1000 * (10/100)));
return 0;
}
Result with both -O0 and -O3 is the same:
1000 * 0.1 = -957043896
1000 * (10/100) = 0
(int)1000 * 0.1 = 100
(int)1000 * (10/100) = 0
I expect a non-sensical result for the first two (I don't know why but I expect passing a double to int argument shouldn't work). However the difference between 3 and 4 is puzzling to me. I expected (10/100) to be calculated on compile time and render the same result as 3.
Can someone explain to me why such result happens, and what is the proper/safe way to do integer-based divisions here?
printf("1000 * 0.1 = %d\n", (1000 * 0.1));
// int double
int * double gives a double. You're trying to print a double with "%d" which is Undefined Behaviour (usually written UB). Try printf("1000 * 0.1 = %f\n", 1000 * 0.1);
printf("1000 * (10/100) = %d\n", (1000 * (10/100)));
// int int int
int / int does integer division, with no decimals. 10/100 yields 0 (and a remainder of 10)
printf("(int)1000 * 0.1 = %d\n", (int)(1000 * 0.1));
// int double
the double 100.0 is converted to int and printed naturally. Note that it's possible that 1000 * 0.1 would generate 99.999999635264318 which would convert to 99
printf("(int)1000 * (10/100) = %d\n", (int)(1000 * (10/100)));
// int int int
10/100 is integer division ... is 0 in this case, same as 2nd statement above.
There is a difference for example between these two calls of printf
printf("1000 * 0.1 = %d\n", (1000 * 0.1));
printf("1000 * (10/100) = %d\n", (1000 * (10/100)));
In the firs call the expression 1000 * 0.1 has the type double but you are using the incorrect conversion specifier %d that is designed for objects of the type int.
In the second call the expression 1000 * (10/100) indeed has the type int. Pay attention to that the casting of the expression to the type int like (int)(1000 * (10/100)) is redundant and does not make a sense. Instead you could write for example ( int )( 1000 * (10.0/100) ). So this call is correct. However the value of the original outputted expression is equal to 0 due to the integer arithmetic.

C - division doesnt work [duplicate]

This question already has answers here:
What is the behavior of integer division?
(6 answers)
Why do we separately cast to "float" in an integer division?
(4 answers)
Closed 5 years ago.
I'm actually totally stuck I don't understand the behavior of this function:
#include <stdio.h>
typedef struct s_resolution
{
int x;
int y;
float fx;
float fy;
} t_resolution;
typedef struct s_pixel_info
{
int tablen;
t_resolution resolution;
char name;
int line;
int pos_suite[6];
int suite[6];
} t_pixel_info;
void get_proportion_ratio(t_pixel_info DataB, t_pixel_info pix_info,
t_resolution *proportion)
{
proportion->fx = (float)(DataB.resolution.x / pix_info.resolution.x);
//I also tried without the cast
proportion->y = (int)(DataB.resolution.y / pix_info.resolution.y * 100);
//if (proportion->y != 100)
printf("%d | %d | %d\n",proportion->y, DataB.resolution.y, pix_info.resolution.y);
}
int main()
{
t_pixel_info DataB;
t_pixel_info pix_info;
t_resolution proportion;
DataB.resolution.x = 5;
pix_info.resolution.x = 10;
DataB.resolution.y = 5;
pix_info.resolution.y = 10;
get_proportion_ratio(DataB, pix_info, &proportion);
}
DataB.resolution.y, pix_info.resolution.y and proportion->y are all Int type.
My problem is that I have this result:
0 | 5 | 10
The operation only works when the result is 100... I must be missing something obvious but I've no idea what.
All of your divisions are being done on integers. Take this expression:
5 / 10 * 100
This groups as:
(5 / 10) * 100
This evaluates to 0: 5 / 10 is 0, and 0 * 100 is still 0. Casting the result after the fact doesn't change it.
If you multiply by 100 before you divide, you will obtain two more digits of precision:
100 * 5 / 10
This evaluates to 50: 100 * 5 is 500, and 500 / 10 is 50.
You could also perform the arithmetic in floating point, e.g.
(double) 5 / (double) 10 * (double) 100
Or you could just cast the first operand and let the standard arithmetic conversions handle the rest; the result is equivalent:
(double) 5 / 10 * 100
In either case, the result will be 50.0
Since resolution.x and resolution.y are ints, the division between them will done as integer division, which keeps only the "whole" part of the division. If you want to perform a floating point ("regular") division, you should cast to a floating point type before performing the division. E.g.:
proportion->fx = ((float) DataB.resolution.x) / ((float) pix_info.resolution.x);

Issue with fahrenheit conversion formula in C [duplicate]

This question already has answers here:
Why does dividing two int not yield the right value when assigned to double?
(10 answers)
Why does division result in zero instead of a decimal?
(5 answers)
Closed 9 years ago.
When writing a program in C to convert celsius to fahrenheit, the following formula gives the incorrect output:
int fahr = 9 / 5 * celsius + 32;
Now, I understand that this is probably an issue with 9/5 being interpreted as an integer, but what I don't understand is that using double or floatit still gives the same incorrect output.
Oddly enough the following formula gives the correct output despite also setting the type to int:
int fahr = celsius / 5 * 9 + 32;
Furthermore, i've noticed even something as simple as the below, when the type is set to double, still gives the output as 1.0 instead of 1.8:
double x = 9 / 5;
printf("%lf\n", x);
I've read this thread:
C program to convert Fahrenheit to Celsius
but I still don't understand why int fahr = celsius / 5 * 9 + 32; works but not int fahr = 9/5 * celsius+32; ?
You're doing math with integers. This expression:
9 / 5
Yields 1 in C. When you say you used double or float, you probably just changed the type of fahr, which doesn't do anything to the operations taking place on the right side of the assignemtn operator. To get the right behaviour, you need to make at least one of those constants a double, too:
9.0 / 5
Likewise, in this statement:
double x = 9 / 5;
You're still doing integer math, and then assigning the result to a double variable. There isn't anything else going on. You'll get the right answer by doing one of these:
double x = 9.0 / 5;
double x = 9 / 5.0;
double x = 9.0 / 5.0;
The reason this expression:
int fahr = celsius / 5 * 9 + 32;
appears to work is just an order of operations thing - here you divide the input by 5 and then multiply by nine, rather than doing the constant operation first. You'd still get more accurate answers by doing:
int fahr = celsius * 9 / 5 + 32;
Besides that, you could also do floating point math in this expression:
int fahr = celsius * 9.0 / 5 + 32;
If you want to do the original calculation using integers, you certainly can - you just need to multiply before dividing:
int fahr = 9 * celsius / 5 + 32;
This expression is equivalent to one of the ones used above.
I still don't understand why int fahr = celsius / 5 * 9 + 32; works but not int fahr = 9/5 * celsius+32;
For the former, you probably declared celsius as a float or as a double, making the entire right side evaluate as such. Assuming you used float, it works out like this:
celsius / 5 * 9 + 32
(celsius / 5.0) * 9 + 32
(celsius / 5.0 * 9.0) + 32
(celsius / 5.0 * 9.0 + 32.0)
For the latter, 9/5 is integer arithmetic that evaluates to 1 before the rest of the math happens as floating point. In this case:
9 / 5 * celsius + 32
1 * celsius + 32 // Because of this, you get an incorrect answer
celsius + 32
celsius + 32.0
Note the the type of the left hand side is irrelevant; the right-hand side is evaluated without regard to that.
Update: You said celsius is an int, which means you just happened to get lucky and test with a value that is a multiple of 5, giving you a correct integer result to celsius / 5 before doing valid integer arithmetic for the rest of the statement. In your second example, being a multiple of 5 doesn't help you.
In any case, now you know why you got lucky, but the linked question gives you the answer to what you actually need to to do have a formula that works when celsius isn't a multiple of 5: use floating point math, as demonstrated in all of the answers there.
The type of each expression or subexpression is (in most cases) evaluated without regard to the context in which it appears.
In this declaration:
double x = 9 / 5;
the initialization expression is 9 / 5; it consists of two int expressions and a division operator. Since the operands of / are of type int it's an int division, resulting in an int value. Since integer division truncates, the result is 1, of type int.
The result of that expression is then used to initialize x. Since x is of type double, the value is implicitly converted from int to double, resulting in x holding the value 1.0.
If you want the value of x to be 1.8, you need to do floating-point division, which means you need floating-point operands. The simplest and clearest way to do this is:
double x = 9.0 / 5.0;
There are several other (IMHO less clear) approaches. If a / operator has two operands, one of type int and one of type double, the int operand is promoted to double, so either of these will also set x to 1.8:
double x = 9.0 / 5;
/* or */
double x = 9 / 5.0;
But be careful with this approach:
double y = 9 / 5 / 3.0;
This is equivalent to:
double y = (9 / 5) / 3.0;
which computes 9 / 5 as an int, yielding 1, then promotes that result to double and divides it by 3.0, yielding 0.333333333.
The point is that the context of an expression does not impose a type on the expression or its operands; the expression is evaluated as if it were isolated, and then the result may be converted depending on its context.

C math calculation not working as expected

I have the following in a program (part of a much larger function, but this is the relevant testing bit):
int test = 100 + (100 * (9 / 100));
sprintf (buf, "Test: %d\n\r", test);
display_to_pc (buf, player);
Basically it amounts to:
x = a + (a * (b / 100))
Where a is a given figure, b is a percentage modifier, and x is the result (the original plus a percentage of the original)... I hope that makes sense.
It gives me:
Test: 100
I thought the math in my head might be wrong, but I've checked several calculators and even the expression evaluator in my IDE, and they all give me the expected result of 109 for the first expression.
Can anyone enlighten me as to what I'm missing here?
Thanks much. :)
Replace
int test = 100 + (100 * (9 / 100));
with
int test = 100 + (100 * 9 / 100);
// x = a + (a * b / 100)
and it will work as expected. 9 / 100 is performed using integer division; the nearest integer to .09 is 0 (and 0 * 100 is still 0).
Doing the multiplication first results in 900 / 100, which gives you the 9 that you were expecting.
If you need more than integer precision, you may need to go the floating point route.
You're using integer math.
9/100 = 0.
100 + (100 * (0) = 100.
Your calculators use floating point math, and can handle decimals appropriately.
As others have pointed out, the problem is that you are doing integer arithmethic. You need to do the calculation as floating point by casting the variable to double or using a double constant, then allow truncation to give you just the integer portion.
x = a + (a * (b / 100.0));
or
x = a + (a * ((double)b / 100)));
Your mistake is that 9 / 100 is interpreted as integer division, and evaluates to 0 and not 0.09.
You can write 9 / 100.0 instead, or rearrange the expression.
int test = 100 + (100 * (9 / 100));
9/100 = 0
0 * 100 = 0
100 + 0 = 100
you are using integer division so 9 / 100 is zero so test = 100 + 0 = 100
Use Daniel L's answer if you will only be working with expressions that will result in whole integer values. If the values you'll be working with are less clean, use double literals instead of integer literals:
int test = 100.0 + (100.0 * (9.0 / 100.0));
The answer of 9/10 gets truncated to 0, and then you multiply that by 100, and then add 100 to it.
Change:
int test = 100 + (100 * (9 / 100));
to
int test = (int)(100 + (100 * (9 / 100.0)));
and see if it works as expected.
EDIT: wow. Lots of answers while I was typing. Most of them will work, too.
You should be using floating point arithmetic so 9/100 becomes 0.09.
int test = 100.0 + (100.0 * 9.0 / 100.0);
You are using integers for your variable types, so the inner most expression (9 / 100) will result in a 0. Then the next expression would be 100 * 0, which is 0, and finally 100 + 0...
To get your desired result try using float instead:
float test = 100.0 + (100.0 * (9.0 / 100.0));
printf("result: %0.2f\n", test);

Resources