C print issue, Decimals equating to 0 - c

Im essentially brand new to C, so bear with me. So basically i have to create a program to calculate the amount of dough per sqft. After rechecking my math and debugging for a very long time; ive found that sradius/INCHES_PER_FEET is coming out to 0.
INCHES_PER_FEET = 12. Now the issue is if i input any value equal to or greater than 12 for the radius, the function will work properly; but if i input 8, and 8/12 is less than 1 a decimal, the program will automatically equate it to 0 and im not sure how i can fix that. Insight would be really appreciated.
int main(){
//define radius variables
int sradius;
printf("What is the radius of your small pizza, in inches?\n");
scanf("%d", &sradius);
int mradius;
printf("What is the radius of your medium pizza, in inches?\n");
scanf("%d", &mradius);
int lradius;
printf("What is the radius of your large pizza, in inches?\n");
scanf("%d", &lradius);
//define pizzas sold variables
int spizzas;
printf("How many small pizzas do you expect to sell this week?\n");
scanf("%d", &spizzas);
int mpizzas;
printf("How many medium pizzas do you expect to sell this week?\n");
scanf("%d", &mpizzas);
int lpizzas;
printf("How many large pizzas do you expect to sell this week?\n");
scanf("%d", &lpizzas);
//dough calculation per size
double sdough,mdough,ldough;
sdough = (PI*((sradius/INCHES_PER_FEET)*(sradius/INCHES_PER_FEET))*DOUGH_PER_SQFT);
mdough = (PI*((mradius/INCHES_PER_FEET)*(mradius/INCHES_PER_FEET))*DOUGH_PER_SQFT);
ldough = (PI*((lradius/INCHES_PER_FEET)*(lradius/INCHES_PER_FEET))*DOUGH_PER_SQFT);
//final amount of dough
double fdough;
fdough = ((sdough*spizzas)+(mdough*mpizzas)+(ldough*lpizzas));
//print statement
printf("you need to order %.3f " ,fdough);
return 0;
}

Cast all the radius into a double before calculating and you will get a double as the result like this:
double sdough,mdough,ldough;
sdough = (PI*(((double)sradius/INCHES_PER_FEET)*((double)sradius/INCHES_PER_FEET))*DOUGH_PER_SQFT);
mdough = (PI*(((double)mradius/INCHES_PER_FEET)*((double)mradius/INCHES_PER_FEET))*DOUGH_PER_SQFT);
ldough = (PI*(((double)lradius/INCHES_PER_FEET)*((double)lradius/INCHES_PER_FEET))*DOUGH_PER_SQFT);

C typically allows you to do operations on a single "data-type". However, if you try to do such operations, C has some preset defaults. For example, in the following code, C will assign the value of a as 0.0000 and not 0.6666, even though you have declared a as float:
int main(void)
{
float a;
int b=2, c=3;
a=b/c;
printf("%f",a);
return 0;
}
This happens because b and c are declared integers. You use type-casting in such cases, i.e., force-changing the declared data-type. The above code will give you desired output if you do the following:
int main(void)
{
float a;
int b=2, c= 3;
a=(float)b/(float)c;
printf("%f",a);
return 0;
}
The answer answered by #cool-guy depicts the same, in your specific case.

The excessive use (IMNSHO) of parentheses is forcing the division to be integer. If you had written
x = PI * sradius / INCHES_PER_FEET * sradius / INCHES_PER_FEET * DOUGH_PER_SQFT;
instead of
x = (PI*((sradius/INCHES_PER_FEET)*(sradius/INCHES_PER_FEET))*DOUGH_PER_SQFT);
the divisions would have been done in floating point and you would get a more accurate value. Assigning that float value to an int causes truncation instead of rounding, so the accuracy could be improved by adding a half:
x = PI * sradius / INCHES_PER_FEET * sradius / INCHES_PER_FEET * DOUGH_PER_SQFT + 0.5;
Most compilers will complain about the implicit conversion to int if warning diagnostics are sufficiently enabled.
The other answers are correct in that forcing type conversion with a typecast will also get an accurate result. Or you could simply define the denominator as a float constant:
const float INCHES_PER_FEET = 12.0;
This requires each division to be done in floating point even though the numerator is an int.

Related

C unsigned long with casting not adding correctly

I can't get the correct value of 15136704000 for the third print line and I am not sure what the issue is. It works correctly when compiled via gcc on Linux but Windows keeps spitting out nonsense and I just would like to understand why.
Windows displays it as Which is 2251802112 inches away.
#include <stdio.h>
int main(void)
{
const int five = 5;
const int eight = 8;
const int mi_to_in = 63360;
int miles_to_moon = 238900;
int km_to_moon = (float) eight / five * miles_to_moon;
unsigned long inches_to_moon = (long) miles_to_moon * mi_to_in;
printf("The moon is %d miles away.\n", miles_to_moon);
printf("Which is equivalent to %d kilometers away.\n", km_to_moon);
printf("Which is %lu inches away.\n", inches_to_moon);
}
As commented by #jamesdlin, the expression (long)miles_to_moon * mi_to_in causes an arithmetic overflow on Windows because the type long only has 32 bits on this system, including on its 64-bit version. Using unsigned long long for this computation would solve the problem, and you should actually use long for mi_to_in and miles_to_moon for portability to some systems.
The C Standard provides fixed length integer types such as int32_t and int64_t defined in <stdin.h> on systems that support them. These types could be used for these variables with the proper range, but for better portability and simplicity, you should use double for such computations:
#include <stdio.h>
int main() {
double mi_to_in = 63360; /* exact figure */
double mi_to_km = 1.60934; /* exact figure */
double miles_to_moon = 238900; /* average distance approximation */
double km_to_moon = miles_to_moon * mi_to_km;
double inches_to_moon = miles_to_moon * mi_to_in;
printf("The moon is %.0f miles away.\n", miles_to_moon);
printf("Which is equivalent to %.0f kilometers away.\n", km_to_moon);
printf("Which is %.0f inches away.\n", inches_to_moon);
return 0;
}
Output:
The moon is 238900 miles away.
Which is equivalent to 384471 kilometers away.
Which is 15136704000 inches away.
Note however that multiplying an approximate figure by an exact one does not increase the precision, which the number of significant digits in the above output might suggest. Rounding these figures seems preferable, yet this would produce 384500 km, which is not the commonly used figure 384400 km.
A more precise average semi-axis is 384399 km, approximately 238855 miles, commonly converted to 238900 mi.
Rounding to a specified number of significant digits is not simple and there is no standard function in the C library to do it. You can use snprintf with %.3e to produce the digits in exponential format, and convert back using strtod, but is cumbersome and inefficient.

Why do the results of my program to find the coordinates of an arc or circle in C differ from the 'correct' results?

I am a real beginner here and I'm really not sure about this. It is a homework assignment.
We have to find 10 (x,y) coordinates of an arc using the radius, a starting angle and an end angle. The program works, but the results it gives differ very slightly from the 'correct' results as required by the automatic checking system. Here's the code and both mine and the systems results based on r=100, angle1=1, anglef=30!
Thanks in advance!
FILE *pf1;
int n=0;
double angulo1, angulof, angulo, radio, x, y;
printf ("\nIntroduce radio : ");
scanf ("%lf", &radio);
printf ("\nIntroduce angulo inicial : ");
scanf ("%lf", &angulo1);
printf ("\nIntroduce angulo final : ");
scanf ("%lf", &angulof);
angulo = ((angulof-angulo1)/9);
pf1 = fopen("salida.txt", "w");
for (n=0; n<=9; n++)
{
x=radio*cos(angulo1+(angulo*n));
y=radio*sin(angulo1+(angulo*n));
fprintf (pf1, "%lf,%lf\n", x,y);
}
return 0;
.
ERROR
■■■ MY FILE:
54.030231,84.147098
-41.614684,90.929743
-98.999250,14.112001
-65.364362,-75.680250
28.366219,-95.892427
96.017029,-27.941550
75.390225,65.698660
-14.550003,98.935825
-91.113026,41.211849
-83.907153,-54.402111
■■■ CORRECT FILE:
54.030231,84.147095
-41.614685,90.929741
-98.999252,14.112000
-65.364365,-75.680252
28.366219,-95.892426
96.017029,-27.941549
75.390228,65.698662
-14.550003,98.935822
-91.113029,41.211849
-83.907150,-54.402111
The post is very confusing:
Calculating angles from 1 to 30 radians in 10 steps doesn't make much sense. Sensible values for radians are from -2π to +2π, outside that range trigonomic functions quickly lose precision. Also, making steps that are much larger than a few degrees is very unusual. To get from 1 to 30 radians in 10 steps, steps of almost 180° are taken.
Some testing of the output reveals that the steps are smaller: from 1 to 10 radians in 10 steps. This is still 57° per step, and goes almost 2 times around the circle.
Reverse engineering the output with atan2(y,x) reveals that the desired output is less precise than the calculation with doubles. So, probably the calculations used 32 bit floats. To test this, one has to be very careful. Internally, floats can get passed as doubles, and the processor works with 80 bits of precision for arithmetic calculations. (Note that on most machines long double has the same precision as double.)
Now, if you call sin on a float, the compiler often calls the double version of sin. To force the float version, one can try to explicitly call them, they have an f appended to the function name: sinf and cosf.
Testing the following with MicroSoft Visual C, 2017 community edition:
#include <math.h>
void test_sinf()
{
float radio = 100;
float angulo1 = 1;
float angulof = 10;
float angulo = (angulof - angulo1) / 9;
float x, y;
int n;
for (n = 0; n < 10; ++n) {
x = radio * cosf(angulo1 + (angulo*n));
y = radio * sinf(angulo1 + (angulo*n));
printf("%.6lf,%.6lf\n", x, y);
}
}
outputs:
54.030228, 84.147095
-41.614685, 90.929741
-98.999252, 14.112000
-65.364365, -75.680252
28.366220, -95.892426
96.017029, -27.941549
75.390228, 65.698662
-14.550003, 98.935822
-91.113022, 41.211849
-83.907150, -54.402115
This leaves the last digit of only 4 of the numbers with a difference. Which suggests a slightly different library/compiler has been used. As the angles and the radius are all integer numbers which can be represented exact with floats, they are an unprobable cause of the differences.
edit: Testing out the suggestion of #gnasher729 is seems he's right. Running the code with the double precision sin and cos, and convering the result to float before printing, gives exactly the "desired" numbers. This probably gives the same results on most compilers for this test case. (32 bit floats are an IEEE standard, and 64 bit trigonomic functions have enough precision to make implementation details disappear after rounding.)
#include <math.h>
void test_sin_converted_to_float()
{
float radio = 100;
float angulo1 = 1;
float angulof = 10;
float angulo = (angulof - angulo1) / 9;
float x, y;
for (int n = 0; n <= 9; ++n) {
x = radio * cos(angulo1 + (angulo*n));
y = radio * sin(angulo1 + (angulo*n));
printf("%.6lf, %.6lf\n", x, y);
}
}
Checking your data with a spreadsheet, it contains exactly what it ought to contain. The data in the second file however look like sine and cosine where calculated with single precision (float).
Which would mean that whoever created this "automatic checking" should be very, very, ashamed of themselves.

Why doesn't roundf() round a float value and why do int - float math operations return wrong values?

I don't understand why doesn't the roundf() function from math.h round the donation variable, whilst it rounds livestockPM without a problem. I need to use the rounded values for other calculations, but I'm using printf to check if the values are correct, and it simply returns wrong values (doesn't round variable donation). Also, the variable final only returns values as if rounded to .00, doesn't matter what variables farmer1,2,3 hold.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main(){
int farmer1 = 9940;
int farmer2 = 4241;
int farmer3 = 7779;
float livestockPM = (float)farmer1 / (float)farmer2;
printf("livestock: %f\n",livestockPM);
livestockPM = roundf(livestockPM * 100) / 100;
printf("livestock rounded: %f\n",livestockPM);
float donation = (float)livestockPM * (float)farmer3;
printf("donation: %f\n", donation);
donation = roundf(donation * 100.00) / 100.00;
printf("donation rounded: %f\n", donation);
float final = donation * (float)farmer2;
printf("final: %f\n", final);
return 0;
}
Output:
livestock: 2.343787
livestock rounded: 2.340000
donation: 18202.859375
donation rounded: 18202.859375
final: 77198328.000000
Anyone got any idea why? I was thinking because of multiplying float with int, but I can't seem to get it work like this. I've tried removing the (float) from integer variables, but the results were undesirable as well. Thanks.
OP's float is encoded using binary floating point and 18202.859375 lacks precision to take on a value that "%f" prints as 18202.860000.
A float cannot represent every possible number. As a binary floating point number it can represent numbers like below. See IEEE 754 Converter, but not in between.
18202.859375
18202.86138125
When the following executes, the best possible result is again 18202.859375.
float donation_rounded = roundf(18202.859375 * 100.00) / 100.00;
Recall that printf("%f\n", x) prints a number rounded textually to the closest 0.000001 value.
Code could use double, but the same problem will occur with very large numbers, but may meet OP''s immediate need. #user3386109
As OP appears to be trying to cope with money, there is no great solution in standard C. best money/currency representation goes into some of the issues.

Result is being rounded up [C] [duplicate]

This question already has answers here:
C program to convert Fahrenheit to Celsius always prints zero
(6 answers)
Closed 7 years ago.
I've been writing this program in C, and I've noticed that the division result, captured in the fee variable, has always fixed value, and that is 5.00, but the result should be 5.78.
Can you explain why it has this behaviour and what should I do to fix it
?
#include <stdio.h>
#include <stdlib.h>
int main(void){
printf("Input package dimensions: width, heigth, length \n");
int width, height, length;
scanf("%d", &width );
scanf("%d", &height );
scanf("%d", &length );
int weight = width*height*length;
printf("%d\n", weight);
float fee = weight/166;
printf("%.2f\n", fee);
printf("The fee is : $%.2f\n and", fee);
system("pause");
return 0;
}
Both weight and 166 have type int, therefore weight/166 is an integer division, which truncates any fractional part. The fact that you assign the result to a variable of type float is irrelevant.
You want to instead perform floating-point division, which you can accomplish by ensuring that at least one of the operands has a floating-point type. One of the simplest ways to do that would be
float fee = weight / 166.0;
Thats because you are dividing int by int. To get a floating point number at least one of them should be a floating number.
float fee = weight/166.0;
Try:
float fee = (float)weight/166.0;
Otherwise an integer-division is performed and then casted to float.
float fee = weight/166;
166 is int and wight is int. int divided by another int will always result in int and only when the result is stored in fee, it is casted to float.
You can fix it by
float fee = (float)weight/166;
or by
float fee = weight/166.0;
In this line weight and 166 will be divided as integers and then cast to float.
float fee = weight/166; // integer division
You need to cast or define one of them as float for a more accurate division.E.g.
float fee = weight/166.0; // double precision division
Or
float fee = (float) weight/166; // single precision division (float)
Or if you want to surprise your colleagues :
float fee = weight/166.0f; // single precision division (float)
That's because dividing an integer by an integer results in an integer, And that's what weight/166 does. It is later covered to a floating point, but that's "too late".
The most explicit way to have a floating point division in your case is:
(float)weight / 166.0f
This should fix it.
float fee = weight/166.0;

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