Am I dividing in the right way in C? - c

I need to apply a formula to three variables. Some of the operations (divisions) give me a 0 instead of the proper number. So I get a different result from what I expected from the formula.
I think that the problem is related to the way C manages data types and their remainders. For this reason, I tried to transform int variables into float variables or to round the numbers that I divided. But all of this is still not working and I'm not able to understand what I'm missing.
Could you please have a look at my code and let me know where is the mistake?
Thanks
double grade(int lc, int wc, int sc)
{
wc = (float)wc;
lc = (float)lc;
sc = (float)sc;
float L = round((wc/100)/lc);
float S = round((wc/100)/sc);
float index = 0.0588 * L - 0.296 * S - 15.8;
return index;
}

Problem:
wc = (float)wc;
lc = (float)lc;
sc = (float)sc;
All these statements do not do what you think because the types of these variables are originally int.
You are converting an int to float and assigning it back to int.
Solution:
Pass the values to a float rather than int to the function, implicit conversion will take care of the rest.
Change your function signature to
double grade(float lc, float wc, float sc)

Or just do this (the other operands will not need the cast to float since it enough if only one of the operands is it, then the others will be converted to it implicitly)
double grade(int lc, int wc, int sc)
{
float L = round(((float)wc/100)/lc);
float S = round(((float)wc/100)/sc);
float index = 0.0588 * L - 0.296 * S - 15.8;
return index;
}
Note that the return type is double, but you use just floats. Use double instead of floats in the function as types as well OR change return type to float.
The mistake is that this wc = (float)wc; is essentially this wc = (int)(float)wc; since wc type is int. Basically nothing happens, therefore when you make your calculation like wc/100, then this will be an integer division resulting in integer, so if wc is less than 100 (and >= 0), then the result is 0 and not a real number as you would expect.

wc = (float)wc; casts an int to a float, converts back to int, then assigns. No real benefit here.
wc/100 is integer division, which discards the fraction of the quotient. Not likely what OP wants.
Converting int to float risks losing precision as so a less precise answer. double is better for wide ranging int values.
Code mixes uses of float and double with a call to a double round(double), double multiplication and conversions from float to double to float to double. Simplify and use double throughout.
double grade(int lc, int wc, int sc) {
// v------v `double` division
double L = round(wc/100.0/lc);
double S = round(wc/100.0/sc);
return 0.0588 * L - 0.296 * S - 15.8;
}

Related

Two different answers for same expression in C

I have an expression which does the same calculation. When I try to do the whole calculation in a single expression and store it in variable "a", the expression calculates the answer as 0. When I divide the equations in two different parts and then calculate it, it gives the answer -0.332087. Obviously, -0.332087 is the correct answer. Can anybody explain why is this program misbehaving like this?
#include<stdio.h>
void main(){
double a, b, c;
int n=0, sumY=0, sumX=0, sumX2=0, sumY2=0, sumXY=0;
n = 85;
sumX = 4276;
sumY = 15907;
sumX2 = 288130;
sumY2 = 3379721;
sumXY = 775966;
a = ((n*sumXY) - (sumX*sumY)) / ((n*sumX2)-(sumX*sumX));
b = ((n*sumXY) - (sumX*sumY));
c = ((n*sumX2) - (sumX*sumX));
printf("%lf\n", a);
printf("%lf\n", b/c);
}
Output:
0.000000
-0.332097
In your program
a = ((n*sumXY) - (sumX*sumY)) / ((n*sumX2)-(sumX*sumX));
all the variables in the right hand side are of type int, so it will produce a result of type int. The true answer -0.332097 is not a int value, so it will be converted to a valid int value, namely 0. And this 0 is assigned to variable a.
But when you do
b = ((n*sumXY) - (sumX*sumY));
c = ((n*sumX2) - (sumX*sumX));
printf("%lf\n", b/c);
The variable b and c are of type double, so the expression b/c produce a double typed value and the true answer -0.332097 is a valid double value. Thus this part of your code give a right result.
In first equation i.e. a = ((n*sumXY) - (sumX*sumY)) / ((n*sumX2)-(sumX*sumX)) both numerator and denominator will give integer results and the value stored in a will also be integer as integer/integer is integer. In second and third expression as you are solving them individually both b and c will be stored in double and double/double will result in a double i.e. a decimal value.
This problem can be solved by using type casting - or better still using float for the variables.
Add double before your calculation, so after you do your integer calculation in "a", it will convert it to double.
a = (double)((n*sumXY) - (sumX*sumY)) / ((n*sumX2)-(sumX*sumX));
First of all (INTEGER)/(INTEGER) is always an INTEGER. So, you can typecast it like a = (double)(((n*sumXY) - (sumX*sumY)) / ((n*sumX2)-(sumX*sumX)));
OR
We know that any number (n ∈ ℂ), multiplied by 1.0 always gives the same number (n). So, your code shall be like:
a = ((n*sumXY*1.0L) - (sumX*sumY)) / ((n*sumX2)-(sumX*sumX));
Multiplying by 1.0L or 1.0f converts the whole arithmetic operation to long double data type.
Now you can print the number (-0.332097) to stdout.
Non-standard Code
Your code is:
void main()
{
//// YOUR CODE
}
Which is non-standard C. Instead your code should be like:
int main(int argc, char **argv)
{
//// YOUR CODE
return 0;
}
Change all your INTEGERS to DOUBLES. That should solve the problem
The type of 1st expression is int whereas in 2nd expression it is double.

Trouble when computing modulos with floats in C

I am not an expert in programming, and I am facing the following issue.
I need to compute modulo between floats A and B.
So I use fmod((double)A, (double)B).
Theorically, if A is a multiple of B, then the result is 0.0.
However, due to floating point precision purpose, A and B are not exactly the number I expected to have.
Then, the result of the modulo computation is not 0.0, but something different.
Which is problematic.
Example:
A=99999.9, but the compiler interprets it as 99999.898.
B=99.9, but the compiler interprets it as 99.900002.
fmod(A,B) expected to be 0.0, but gives actually 99.9.
So the question is: how do you use to manage this kind of situation ?
Thank you
The trouble is that:
A is not 99999.9, but 99999.8984375 and
B is not 99.9, but 99.90000152587890625 and
A mod B is 99.89691162109375
OP is getting the correct answer for the arguments given.
Need to use different augments.
A reasonable alternative is to convert the arguments by a scaled power-of-10, then round to an integer, %, back to floating point and un-scale.
Overflow is a concern.
Since OP wants to treat numbers to the nearest 0.1, scale by 10.
#include <float.h>
#include <stdio.h>
int main(void) {
float A = 99999.9;
float B = 99.9;
printf("%.25f\n", A);
printf("%.25f\n", B);
printf("%.25f\n", fmod(A,B));
long long a = lround(A*10.0);
long long b = lround(B*10.0);
long long m = a%b;
double D = m/10.0;
printf("D = %.25f\n", D);
return 0;
}
Output
99999.8984375000000000000000000
99.9000015258789062500000000
99.8969116210937500000000000
D = 0.0000000000000000000000000
Alternative
long long a = lround(A*10.0);
long long b = lround(B*10.0);
long long m = a%b;
double D = m/10.0;
Scale, but skip the integer conversion part
double a = round(A*10.0);
double b = round(B*10.0);
double m = fmod(a,b);
double D = m/10.0;

Best practices for float multiplication in C++ or C?

I need to perform a simple multiplication of 400 * 256.3. The result is 102520. Straight forward and simple. But to implement this multiplication in C++ (or C) is a little tricky and confusing to me.
I understand floating point number is not represented as it is in computer. I wrote the code to illustrate the situation. Output is attached too.
So, if I do the multiplication using float type variable, I am subjected to rounding error. Using double type variable would have avoided the problem. But let's say I have a very limited resource on the embedded system and I have to optimize the variable type to the very best I could, how can I perform the multiplication using float type variable and not susceptible to rounding error?
I knew the floating point math done by computer is not broken at all. But I am curious for best practice to perform floating point math. 256.3 is just a value for illustration. I would not know what floating point value I will get during runtime. But it is for sure, a floating point value.
int main()
{
//perform 400 * 256.3
//result should be 102520
float floatResult = 0.00f;
int intResult = 0;
double doubleResult = 0.00;
//float = int * float
floatResult = 400 * 256.3f;
printf("400 * 256.3f = (float)->%f\n", floatResult);
//float = float * float
floatResult = 400.00f * 256.3f;
printf("400.00f * 256.3f = (float)->%f\n", floatResult);
printf("\n");
//int = int * float
intResult = 400 * 256.3f;
printf("400 * 256.3f = (int)->%d\n", intResult);
//int = float * float;
intResult = 400.00f * 256.3f;
printf("400.00f * 256.3f = (int)->%d\n", intResult);
printf("\n");
//double = double * double
doubleResult = 400.00 * 256.3;
printf("400.00 * 256.3 = (double)->%f\n", doubleResult);
//int = double * double;
intResult = 400.00 * 256.3;
printf("400.00 * 256.3 = (int)->%d\n", intResult);
printf("\n");
//double = int * double
doubleResult = 400 * 256.3;
printf("400 * 256.3 = (double)->%f\n", doubleResult);
//int = int * double
intResult = 400 * 256.3;
printf("400 * 256.3 = (int)->%d\n", intResult);
printf("\n");
//will double give me rounding error?
if (((400.00 * 256.3) - 102520) != 0) {
printf("Double give me rounding error!\n");
}
//will float give me rounding error?
if (((400.00f * 256.3f) - 102520) != 0) {
printf("Float give me rounding error!\n");
}
return 0;
}
Output from the code above
If you have a fixed number of decimal digits (1 in the case of 256.3) as well as a bounded range of the results, you can use integer multiplication, and adjust for the shift in decimal digits through integer division:
int result = (400 * 2563) / 10;
Rounding errors are inherent to floating point arithmetics, except for a few cases where all operands can be represented exactly. Whether you choose float or double just influences when the error occurs, not if.
First of all, understand that type double has all the same problems as type float. Neither type has infinite precision, so both types are susceptible to precision loss and other problems.
As to what you can do: there are many different problems that come up, depending on what you're doing, and many techniques to overcome them. Many, many words have been written on these techniques; I suggest doing a web search on "avoiding floating point error". But the basic points are:
Know that floating-point results are never exact
Don't try to compare floating-point numbers for exact equality
When comparing floating-point numbers for equality, use an appropriate "epsilon" range
After calculation, it is often appropriate to explicitly round the final value to the desired precision (especially when printing it out)
Beware of algorithms which cause the precision loss to increase with each step
See also https://www.eskimo.com/~scs/cclass/handouts/sciprog.html .
A key weakness to displaying the problem is the conversion to int intResult. The posted problem is about multiplying and comparing, but code only shows issues surrounding int conversion.
If code needs to convert a FP value to the nearest whole number, uses rint(), round(), nearbyint() or lround(), not integer assignment.

Dividing integers in C rounds the value down / gives zero as a result

I'm trying to do some arithmetic on integers. The problem is when I'm trying to do division to get a double as a result, the result is always 0.00000000000000000000, even though this is obviously not true for something like ((7 * 207) / 6790). I have tried type-casting the formulas, but I still get the same result.
What am I doing wrong and how can I fix it?
int o12 = 7, o21 = 207, numTokens = 6790;
double e11 = ((o12 * o21) / numTokens);
printf(".%20lf", e11); // prints 0.00000000000000000000
Regardless of the actual values, the following holds:
int / int = int
The output will not be cast to a non-int type automatically.
So the output will be floored to an int when doing division.
What you want to do is force any of these to happen:
double / int = double
float / int = float
int / double = double
int / float = float
The above involves an automatic widening conversion - note that only one needs to be a floating point value.
You can do this by either:
Putting a (double) or (float) before one of your values to cast it to the corresponding type or
Changing one or more of the variables to double or float
Note that a cast like (double)(int / int) will not work, as this first does the integer division (which returns an int, and thus floors the value) and only then casts the result to double (this will be the same as simply trying to assign it to a double without any casting, as you've done).
It is certainly true for an expression such as ((7 * 207) / 6790) that the result is 0, or 0.0 if you think in double.
The expression only has integers, so it will be computed as an integer multiplication followed by an integer division.
You need to cast to a floating-point type to change that, e.g. ((7 * 207) / 6790.0).
Many poeple seem to expect the right-hand side of an assignment to be automatically "adjusted" by the type of the target variable: this is not how it works. The result is converted, but that doesn't affect any "inner" operations in the right-hand expression. In your code:
e11 = ((o12 * o21) / numTokens);
All of o12, o21 and numTokens are integer, so that expression is evaluated as integer, then converted to floating-point since e11 is double.
This like doing
const double a_quarter = 1 / 4;
this is just a simpler case of the same problem: the expression is evaluated first, then the result (the integer 0) is converted to double and stored. That's how the language works.
The fix is to cast:
e11 = ((o12 * o21) / (double) numTokens);
You must cast these numbers to double before division. When you perform division on int the result is also an integer rounded towards zero, e.g. 1 / 2 == 0, but 1.0 / 2.0 == 0.5.
If the operands are integer, C will perform integer arithmetic. That is, 1/4 == 0. However, if you force an operand to be double, then the arithmetic will take fractional parts into account. So:
int a = 1;
int b = 4;
double c = 1.0
double d = a/b; // d == 0.0
double e = c/b; // e == 0.25
double f = (double)a/b; // f == 0.25

Floating point in C

I am asking a user for two non-negative integer values in C. I then want to convert these to percentages (expressed as decimals). Unfortunately, my floats are coming up as zeroes. Why is this, and how do I fix it?
int a = 5;
int b = 10;
int total = a + b;
float a_percent = a / total;
float b_percent = b / total;
printf("%.2f, %.2f\n", a_percent, b_percent);
You aren't using floats, you're using integers, and so the integral division gives zero (which is then assigned to a float).
To perform a floating-point operation, you must first convert the integers (or at least one of them) to a float. Conveniently, we just use total:
float total = a + b; // exact
float ap = a / total;
float bp = b / total; // OK, these are now floating-point operations
In addition to the problems others have pointed out, the ratio won't be a percentage until you multiply it by 100.0.
An int divided by an int will always return an int. You'll have to make one of the two arguments a float before dividing:
float a_percent = (float) a / total;
float b_percent = (float) b / total;
I am not a C expert, but my guess is because dividing an int by an int always results in an int.
You may need to do something like this:
float a_percent = (float)a/total;
float b_percent = (float)b/total;
You're first performing an integer division, then converting the result to floating point. This will not give the results you want. Either make total a floating point value to begin with (so that the types get automatically promoted right) or cast a and b to (float) before performing the division.
You are using integer math not floating point here.
Try:
float a_percent = a/(float)total;
float b_percent = b/(float)total;
For a simple percentage you may be happier using fixed-point. Just multiply your numerator (a or b) by 100 and you'll get the percentage from the division. forex:
int a = 5;
int b = 10;
int total = a + b;
int a_percent = 100*a/total;
int b_percent = 100*b/total;
printf("a%%=%d, b%%=d\n", a_percent, b_percent);

Resources