Wrong answer of average function? - c

I'm practically new to C programming and I've been trying to get a simple average function right, but the fractional part of the answer keeps messing up...??
#include <stdio.h>
#include <float.h>
float cal(int num1,int num2,int num3);
int main(){
int a,b,c;
float avg;
a=10;
b=5;
c=11;
avg=cal(a,b,c);
printf("Average is : %E\n", avg);
return 0;
}
float cal(int num1,int num2,int num3){
float avg1;
avg1=(num1+num2+num3)/3;
return avg1;
}
The answer (avg) should be 8.66666666667, but instead I get 8.00000000...

You're doing integer division here. Cast it to float (at least one of them) or use float literals before division to force it to use float division.
For example, change
avg1=(num1+num2+num3)/3;
to
avg1=(num1+num2+num3)/(float)3; // 1. cast one to float
avg1=(num1+num2+num3)/3.0f; // 2. use float literals

Change this
avg1=(num1+num2+num3)/3;
to this
avg1=(num1+num2+num3)/(float)3;
That way you force a division by a float.
With your code you actually perform integer division, which means that the decimal digits get discarded. Then the result of the division is assigned to a float number, but the decimal digits are already gone. That's why you need to cast at least one operand of the division to a float, in order to get what you want.

It is because all operands are integer in here (num1+num2+num3)/3. So you get an integer division, that is later cast to a float (i.e. upon the assignment, but after the evaluation).
You need to make one of the division operands a float, so the rest will be converted. And the division will be a float division.
E.g:
(num1+num2+num3)/(float)3
(num1+num2+num3)/3.0f
((float)(num1+num2+num3))/3
Note that the additions are still integer additions, because of parentheses.
A nice read on the conversion rules is here.

Force the division to be perfomed in floating point
avg1=(num1+num2+num3)/3.0f;
What happens in your case is, you perform the an integer division and then convert it to float:
Resulting type of (num1+num2+num3)/3 is an integer, while the type of (num1+num2+num3)/3.0f is a float.
Integer division will give the result without the decimal point.

Change
avg1=(num1+num2+num3)/3;
to
avg1=(float)(num1+num2+num3)/3;
If you perform integer division then result will also be integer.
As avg1 is already declared as float, you can cast the result of the operation to get float value.

You can simplify your code further
float cal(int num1,int num2,int num3){
return ((num1+num2+num3)/3.0);
}
Just change the value 3 to 3.0 that's enough. because the up-casting has to be made manually the compiler only perform the down-casting.

In addition to the well pointed out need to use floating point division rather than integer division, typical float will not provide a precise number like 8.66666666667 but only to 6 or so digits. Further, conversion of typical int (32-bit) may result in truncation when converting to float.
For a more precise answer with 11 digits to the rights of ., use double instead of float
double cal(int num1,int num2,int num3){
double avg1;
avg1=(num1+num2+num3)/3.0; // 3 --> 3.0
return avg1;
}
int main(void){ // added void
int a,b,c;
double avg;
a=10;
b=5;
c=11;
avg=cal(a,b,c);
// printf("Average is : %E\n", avg);
printf("Average is : %.11E\n", avg); // Print to 11 digits after the dp.
return 0;
}

Related

C - int arithmetic calculation with float (beginner)

I have user integer input input and wanted to output the calculation with the input by division. The return had been 0 rather than decimals results. Wanted to prevent use of initialize the variable input with int rather than float to prevent possible errors in later data input with delimiter .
Is there any way to calculate float result w/ int input other than assigning float for the variable input ?
Source:
#include <stdio.h>
#include <stdlib.h>
int main() {
int input;
printf("Enter data:");
scanf("%d", &input);
printf("Output: %f", (input / 7));
return 0;
}
Return:
Input: 6
0.0000
Everything in C has a type, including constants like 7 which is type int, 7.0f which is type float or 7.0 which is type double.
Whenever mixing fixed point and floating point operands in the same operation with two operands (generally a bad idea), then the fixed point operand is converted to floating point. This is called "the usual arithmetic conversions".
Examples:
int input;, input / 7. Both operands are int, no promotion occurs, the result will be of type int. This has everything to do with the / operator and nothing to do with where you place the result. The divison will get carried out on int type, so if you wanted it to be type float, it's already too late. Something like float f = input / 7 will not affect the type used by the division in any way. It will only convert the resulting int to float.
int input;, input / 7.0f. One operand is type int, the other is type float. The usual arithmetic conversions state that the int operand will get converted to float before the division. So this would solve the problem.
However, here is a better idea: Simply never mix fixed point and floating point in the same expression, because the potential for bugs is huge. Instead do this:
scanf("%d", &input);
float f_input = (float)input;
printf("Output: %f", (f_input / 7.0f);
Now nothing goes on implicitly, all implicit conversions have been removed. The cast is not necessary, but creates self-documenting code saying: "yes I do mean to make this a float type rather than had it happen by chance/accident".
(Advanced topic detail: printf actually converts the passed float to double, but we need not worry about that.)
You need input/7 to be performed with floating point math, rather than integer math.
Like this...
printf("Output: %f", (input / 7.0));
This link explains a bit better how C/C++ deals with mixing floats/doubles/ints etc.
Does one double promote every int in the equation to double?

Is there any way to not lose the precision and still get the value?

First off, I'm a total beginner at C, with prior experience of programming in Java and Python. The goal of the program was to add 2 numbers. While I was playing with the code, I encountered an issue with precision. The issue was caused when I added 2 numbers- 1 of float data type and the other of double data type.
Code:
#include <stdio.h>
int main() {
double b=20.12345678;
float c=30.1234f;
printf("The Sum of %.8f and %.4f is= %.8f\n", b, c, b+c);
return 0;
}
Output:
The Sum of 20.12345678 and 30.1234 is= 50.24685651
However, the correct output should be: 50.24685678
float values are accurate up-to 6 decimal places, and so is the output.
I tried casting the values explicitly to double type, but its still of no use.
PS: When I convert the variable type from float to double, the output is precise; but is there any other way to add float and double integers without messing with their data type?
Thank You.
float only guarantees 6 decimal digits of precision, so any computation with a float (even if the other operands are double, even if you're storing the result to a double) will only be precise to 6 digits.
If you need greater precision, then limit yourself to double or long double. If you need more than 10 decimal digits of precision, then you'll need to use something other than the native floating point types and library functions. You'll either need to roll your own, or use an arbitrary precision math library like GNU MP.
The value assigned to c can't be expressed exactly so it gets assigned the next closest value. You don't see that when printing to 4 decimal places but you do see it if you print 8:
printf("The Sum of %.8f and %.8f is= %.8f\n", b, c, b+c);
Output:
The Sum of 20.12345678 and 30.12339973 is= 50.24685651
So the constant 30.1234f is already imprecise enough for the calculation you're trying to do.

While loop involving floating point numbers [duplicate]

Why does this program gives no output for float and double datatypes. However, what will be the result when the same code is replaced with for loop??
# include <stdio.h>
int main()
{
float x=1.1;
while (x==1.1)
{
printf("%f\n",x);
x=x-0.1;
}
return 0;
}
float x=1.1;
while (x==1.1)
float and double variables are not capable of storing the exact value of 1.1, only a very close approximation. The exact value in a float and a double will be slightly different due to the difference in precision.
1.1 is a double value. You are storing 1.1 as a double into a float which will slightly alter the value. Then you compare it with the double value 1.1 so it will not quite be equal and so will never enter your condition.
For this to work you need to write 1.1f to ensure that you are working with the same data type everywhere.
In addition I'm sure someone else will explain why comparing floating point values for exact equality is often a bad idea.

Why did we add a dot in multiplication in order to run the program?

I'm writing a program that calculates the roots of the quadratic equation. When I first wrote the code I didn't type a dot after 4 and 2 in the x equation and it didn't work! So what does that dot represent here and when should I use it?
#include<stdio.h>
#include<conio.h>
#include<math.h>
int main()
{
int a, b, c;
double x;
scanf("%d %d %d", &a, &b, &c);
x = (-b + sqrt(b*b-4.*a*c) ) / (2.*a);
printf("%lf", x);
getch();
return 0;
}
4. is 4.0
The decimal point makes it a float literal rather than an integer literal.
The more important literal is 2. as without it you would get integer division (and in most cases, the wrong result).
Integer literals are interpreted by the compiler as integers, which means that operations such as division are performed in their integer form if all operands are integers. The decimal point makes it a floating literal, which means that the compiler will use the floating form of the operations instead.

Floating point rounding in C

I've run into some weird rounding behaviour with floats. The code below demonstrates the problem. What is the best way to solve this? I've been looking for solutions but haven't had much luck.
#include<stdio.h>
int main(void)
{
float t;
t = 5592411;
printf("%f\n", 1.5*t);
t *= 1.5;
printf("%f\n", t);
return 0;
}
The code above should print out the same value, but I get this on my setup using GCC 4.7.2:
8388616.500000
8388616.000000
If I use a calculator, I get the first value, so I assume the second is being rounded somehow. I have identical Fortran code which does not round the value(has the 0.5).
1.5 is a double constant rather than a float and C has automatic promotion rules. So when you perform 1.5*t what happens is (i) t is converted to a double; (ii) that double is multiplied by the double 1.5; and (iii) the double is printed (as %f is the formatter for a double).
Conversely, t *= 1.5 promotes t to a double, performs a double multiplication and then truncates the result to store it back into a [single precision] float.
For evidence, try either:
float t;
t = 5592411;
printf("%f\n", 1.5f*t); // multiply a float by a float, for no promotion
t *= 1.5;
printf("%f\n", t);
return 0;
Or:
double t; // store our intermediate results in a double
t = 5592411;
printf("%f\n", 1.5f*t);
t *= 1.5;
printf("%f\n", t);
return 0;
The first calculation is done with double precision, the second is calculated the same, but truncated to single precision in the assignment to float.
If you use double for your variable, you'll get the same result. It's a good idea to use this type over float whenever accuracy may be a concern.
In the first case, the result is a double which can precisely represent the desired value.
In the second case, the result is a float which can't precisely represent the desired value.
Try the same with double and you'll end up with the same results either way.
#include<stdio.h>
int main(void)
{
double t;
t = 5592411;
printf("%f\n", 1.5*t);
t *= 1.5;
printf("%f\n", t);
return 0;
}
Writing 1.5 in C code is interpreted as a double, which has more precision than the float type.
The first case,
printf("%f\n", 1.5*t);
results in t being implicitly converted to a double (with greater precision) and then multiplied. The printf function, which casts the input corresponding to %f anyway, prints the result, which is also a double.
The second case has the 1.5 being converted to the float type, which has less precision and cannot store as small details.
If you want to avoid this effect, use 1.5f instead on 1.5 to use floats, or change the type of t to double.
Whether this would work at all depends on the machine representation of floats and doubles. Passing a float on a typical 32 bit architecture pushes 4 bytes on the argument stack. Passing a double would push 8 bytes. Passing a double but using %f is asking to treat it as a float which will look at the first 4 bytes pushed in our typical case. Depending on machine representation this might be close to the intended result or might be way out in left field.

Resources