Finding angles of triangle by given sides in C programming - c

I run it in my code::blocks to show 3 angles of triangle where 3 sides are given by the user. But if I run and give 3 sides such as 3,4,5 output will be -1.#J -1.#J -1.#J. What's wrong with my code?
#include <stdio.h>
#include <math.h>
int main()
{
float a, b, c, A, B, C, R, s, pi, area;
pi = acos(-1);
scanf("%f %f %f", &a, &b, &c);
s = (a+b+c)/2;
area = sqrt(s*(s-a)*(s-b)*(s-c));
R = (a*b*c)/(4*area);
A = (180/pi)*asin(a/2*R);
B = (180/pi)*asin(b/2*R);
C = (180/pi)*asin(c/2*R);
printf("%.2f %.2f %.2f", A, B, C);
return 0;
}

You need more parentheses. You have:
A = (180/pi)*asin(a/2*R);
You need:
A = (180/pi)*asin(a/(2*R));
What you wrote is equivalent to:
A = (180 / pi) * asin((R * a) / 2);
You should also check your inputs so that a 'triangle' with sides 1, 1, 3 is rejected, for example. Negative and zero lengths should probably be rejected too.
Revised code
#include <stdio.h>
#include <math.h>
int main(void)
{
float a, b, c, A, B, C, R, s, pi, area;
pi = acos(-1);
if (scanf("%f %f %f", &a, &b, &c) != 3)
{
fprintf(stderr, "Failed to read 3 numbers\n");
return 1;
}
if (a <= 0 || b <= 0 || c <= 0)
{
fprintf(stderr, "Sides must be strictly positive\n");
return 1;
}
s = (a + b + c) / 2;
if (a > s || b > s || c > s)
{
fprintf(stderr, "The three sides %.2f, %.2f, %.2f do not form a triangle\n",
a, b, c);
return 1;
}
area = sqrt(s * (s - a) * (s - b) * (s - c));
R = (a * b * c) / (4 * area);
A = (180 / pi) * asin(a / (2 * R));
B = (180 / pi) * asin(b / (2 * R));
C = (180 / pi) * asin(c / (2 * R));
printf("Sides: %6.2f %6.2f %6.2f\n", a, b, c);
printf("Angles: %6.2f %6.2f %6.2f\n", A, B, C);
return 0;
}
Note that error messages are reported on standard error. All lines of output end with a newline in the format. The input data is echoed. All of these are good practices.
Example runs
$ triangle <<< "0 1 3"
Sides must be strictly positive
$ triangle <<< "-1 1 3"
Sides must be strictly positive
$ triangle <<< "1 1 3"
The three sides 1.00, 1.00, 3.00 do not form a triangle
$ triangle <<< "3 4 5"
Sides: 3.00 4.00 5.00
Angles: 36.87 53.13 90.00
$ triangle <<< "3 3 3"
Sides: 3.00 3.00 3.00
Angles: 60.00 60.00 60.00
$ triangle <<< "1 1.4141 1"
Sides: 1.00 1.41 1.00
Angles: 45.00 nan 45.00
$ triangle <<< "1 1 1.4141"
Sides: 1.00 1.00 1.41
Angles: 45.00 45.00 nan
$ triangle <<< "1 1 1.414"
Sides: 1.00 1.00 1.41
Angles: 45.01 45.01 89.98
$ triangle <<< "1 1 1.41421356237309504880"
Sides: 1.00 1.00 1.41
Angles: 45.00 45.00 nan
$
I'm a little puzzled about the nan values. However, changing the data type from float to double and adjusting the scanf() formats appropriately (%lf instead of %f) seems to 'resolve' (maybe 'evade' is a better word) that problem.

It should be
A = (180/pi)*asin(a/(2*R));
rather than
A = (180/pi)*asin(a/2*R);
Insufficient parentheses.

Additional detail:
asin(x) is only defined for values [-1.0 ... 1.0]. With select input, corrected code may get a a/(2*R) that is just a little bit greater than 1.0 due to calculation issues with floating point.
s = (a+b+c)/2;
// Jonathan Leffler tests
area = sqrt(s*(s-a)*(s-b)*(s-c));
R = (a*b*c)/(4*area);
// add test
double R2 = R*2.0;
A = (a>R2) ? 180/pi : (180/pi)*asin(a/R2);
...

I could not get your posted code to work, even given all the comments and prior answers.
However, this works very well.
Note: I did not include code to error check the call to scanf() to keep the presentation simple
#include <stdio.h>
#include <math.h>
#define RAD_2_DEG (57.2958)
#define TOTAL_DEG (180.0)
int main( void )
{
int a, b, c; // user entered lengths of sides of triangle
double A, B, C; // calculated angle values in degrees
scanf( "%d %d %d", &a, &b, &c );
// note: acos returns the angle in radians
// and one radian is (approx) 57.2958 degrees
A = RAD_2_DEG * acos((double)(b*b + c*c - a*a)/(2.0*b*c));
B = RAD_2_DEG * acos((double)(c*c + a*a - b*b)/(2.0*a*c));
// third angle done this way to absorb fractional degree errors
C = TOTAL_DEG -(A + B);
printf("%.2f %.2f %.2f", A, B, C);
return 0;
}

Related

Angle in triangle by coordinates C

i have to find angle ∠BAC in triangle ABC with given coordinates. I'm trying to find cos, then use function acos(cos) and get degrees(not radian) anwser.
The input is Ax,Ay,Bx,By,Cx,Cy coordinates
#include <math.h>
int main(){
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int n;
int ax,ay,bx,by,cx,cy;
scanf("%d",&n);
for(int i = 0; i<n; i ++){
scanf("%d %d %d %d %d %d",&ax,&ay,&bx,&by,&cx,&cy);
double cosab = (ax*bx+ay*by)/ (sqrt(ax*ax+ay*ay)* sqrt(bx*bx+by*by));
cosab =180* acos(cosab)/M_PI;
printf("cosab is %0.20g\n",cosab);
}
return 0;
}
With input
8
2 1 2 3 5 5
2 1 4 3 2 3
3 1 3 5 2 3
0 0 1 0 10 0
0 0 1 0 -10 1
7 4 3 3 3 3
0 0 1 0 1 1e-5
0 0 1 0 1e-5 1
I get
cosab is 29.744881296942211
cosab is 10.304846468766044
cosab is 40.601294645004479
cosab is -1.#IND
cosab is -1.#IND
cosab is 15.255118703057764
cosab is -1.#IND
cosab is -1.#IND
But the anwser should be
36.869897645844019962
45
26.565051177077990019
0
174.28940686250035697
0
0.00057295779511172474814
89.999427042204885652
What is "-1.#IND" and what's wrong with my code?
As others have pointed out, the input coordinates are floating point, so let us read them into doubles:
double ax,ay,bx,by,cx,cy;
/* Read coordinates of A, B, and C. */
scanf("%lf%lf%lf%lf%lf%lf",&ax,&ay,&bx,&by,&cx,&cy);
∠BAC is the angle between lines AB and AC. Let us consider those as vectors AB and AC represented by their x and y components:
/* Convert to vectors AB and AC (as x and y components). */
double abx = bx - ax; /* x component of vector AB */
double aby = by - ay; /* y component of vector AB */
double acx = cx - ax; /* x component of vector AC */
double acy = cy - ay; /* y component of vector AC */
Now there is a nice formula using ATAN2 on the vector components to get the angle of rotation from one 2D vector to another1:
/*
* Get angle of rotation from vector AB to vector AC
* in the range [-M_PI, +M_PI].
*/
double rot_ab_ac = atan2(acy*abx - acx*aby, acx*abx + acy*aby);
We want the absolute angle, not a signed angle:
/* Convert to absolute angle BAC. */
double bac = fabs(rot_ab_ac);
Finally, we want the angle in degrees, not radians:
/* Convert to degrees. */
double bac_deg = bac * 180.0 / M_PI;
Note: M_PI is not defined in the C standard, but can be easily defined by a macro if necessary:
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
1 Angle Between Two Vectors 2D Formula
Input is not only integers
1e-5 is like 0.00001. Read that into a double.
// int ax,ay,bx,by,cx,cy;
double ax,ay,bx,by,cx,cy;
...
//scanf("%d %d %d %d %d %d",&ax,&ay,&bx,&by,&cx,&cy);
scanf("%lf %lf %lf %lf %lf %lf",&ax,&ay,&bx,&by,&cx,&cy);
Be careful with acos()
The |x| in acos(x) may be just a tad larger than 1.0 due to computationally issues. Best to check
// add
if (cosab > 1.0) cosab = 1.0;
else if (cosab < -1.0) cosab = -1.0;
cosab = 180 * acos(cosab) / M_PI;
Perhaps better precision
// sqrt(ax*ax+ay*ay)
hypot(ax, ay)
Other issues may exist too
Worth reviewing if proper formula is used: Law of cosines

Roots of equation in C

I am relatively new to C, and am trying to improve myself in it. I made a calculator and added the quadratic equation solver to it, cause i know the formula of finding the roots. But i am faced with two problems.
Code:
#include <stdio.h>
#include <maths.h>
#include <stdlib.h>
#include <windows.h>
main(){
float A1, A2, A, B, C, ans, Z;
printf("Welcome to Quadratic Equation solver. Enter the coefficient of X^2, followed by\nthe coefficient of X, followed by the integer value.\n\nEnter values: ");
scanf("%f%f%f", &A, &B, &C);
CheckF = (B * B - 4 * A * C);
if (CheckF < 0) {
system("COLOR B4");
printf("This calculator HeX, currently cannot handle complex numbers.\nPlease pardon my developer. I will now redirect you to the main menu.\n");
system("pause");
system("cls");
system("COLOR F1");
goto Start;
} else if (CheckF >= 0) {
Z = pow(CheckF, 1/2);
A1 = (-B + Z)/(A+A);
A2 = (-B - Z)/(A+A);
if (A1 == A2) {
ans = A1;
printf("\nRoot of equation is %f (Repeated root)\n", ans);
Sleep(250);
} else if (A1 != A2) {
printf("Roots of equation are %f and %f \n", A1, A2);
Sleep(250);
}
}
}
Problem 1:
When i run the code and input 3 32 2, mathematically the output should be Roots of equation are -0.06287 and -10.6038, that i double checked with my sharp calculator. However, the output that i got was was off: Roots of equation are -5.166667 and -5.500000 i am totally unsure why is it not computing the correct roots of the equation.
Problem 2:
Some roots do not have the coefficient of X^2, for example (2X + 2), which can be solved to get repeated roots of -2, (6X - 3), which gives us that x is 0.5 repeated. However, according to the quadratic equation, which is divided by 2A, will never work, as it is divided by 0. What is the possible way out of this situation? Is it to check if A = 0 then do something else? Any help will be appreciable.
integer division
pow(CheckF, 1/2) is 1.0 as 1/2 is integer division with a quotient of 0.
// Z = pow(CheckF, 1/2);
Z = pow(CheckF, 1.0/2.0);
// or better
Z = sqrt(CheckF);
// Even better when working with `float`.
// Use `float sqrtf(float)` instead of `double sqrt(double)`.
Z = sqrtf(CheckF);
Best - re-write using double instead of float. Scant reason for using float here. double is the C goto floating point type.
Other issue
//#include <maths.h>
#include <math.h>
// main() {
int main(void) {
// CheckF = (B * B - 4 * A * C);
float CheckF = (B * B - 4 * A * C);
// goto Start;
Use an auto formater
I see some problems with the code. First, I suggest you to use double instead of float. They offer much better precision and an ideal calculator needs precision. Secondly, you do:
Z = pow(CheckF, 1/2);
You should use sqrt(CheckF) since there is a dedicated function in C for square roots! The following works for me so if you fix the above two problems, your code will probably work.
int main() {
double A1, A2, A, B, C, ans, Z;
printf("Welcome to Quadratic Equation solver. Enter the coefficient of X^2, followed by\nthe coefficient of X, followed by the integer value.\n\nEnter values: ");
A = 3;
B = 32;
C = 2;
double CheckF = (B * B - 4 * A * C);
if (CheckF >= 0) {
Z = sqrt(CheckF);
A1 = (-B + Z) / (A + A);
A2 = (-B - Z) / (A + A);
if (A1 == A2) {
ans = A1;
printf("\nRoot of equation is %f (Repeated root)\n", ans);
} else if (A1 != A2) {
printf("Roots of equation are %f and %f \n", A1, A2);
}
}
}

Rotation program in C

I'm basically trying to make a math rotation program in C. But the output is always wrong. P(x,y) is rotated about Q(r,s); clockwise (direction=1) or anticlockwise (direction=0). The a,b,c are angles in triple ,I guess question meant c is in hundred's then b is in ten's and a is unit's.
Input:
0
7 3
0 1 1
0 0
Output: -3 7
Whereas I'm getting -5 5.
Thanks for your time if you help me.
Original question link: https://www.codechef.com/problems/DSPC305
i found another question by the same uploader which uses TRIPLE too. He further added a note :Triple is defined by a,b,c where a is base, b is height and c is hypotenuse of a triangle. Each triple corresponds to an angle given by cosA= a/c
#include<stdio.h>
#include<math.h>
int main() {
int x,y,a,b,direction,c,r,s,xnew,ynew;
scanf("%i", &direction);
scanf("%i %i", &x, &y);
scanf("%i %i %i" , &a, &b, &c);
scanf("%i %i", &r, &s);
float PI = 3.1415926535897932384626;
float theta = ((c*100+b*10+a)*PI)/180;
if (direction==1)
{
xnew= (x-r) * cos(theta) + (y-s) * sin(theta);
ynew= -(x-r) * sin(theta) + (y-s) * cos(theta);
printf("%i %i", xnew+r, ynew+s);
}
if (direction==0)
{
xnew =( (x-r) * ((cos(theta))) - (y-s) * sin(theta));
ynew =( (x-r) * ((sin(theta))) + (y-s) * cos(theta));
printf("%i %i", (xnew+r), (ynew+s));
}
return 0;
}
This
float theta = ((c*100+b*10+a)*PI)/180;
has nothing to do with the definition of a triple.
You can use this code:
#include<stdio.h>
#include<math.h>
int main()
{
double xp,yp,xq,yq,a,b,c;
double t,xn,yn;
int z;
scanf("%d",&z);
scanf("%lf%lf",&xp,&yp);
scanf("%lf%lf%lf",&a,&b,&c);
scanf("%lf%lf",&xq,&yq);
t=asin(b/c);
if(z==0)
{
xn=xp*cos(t)-yp*sin(t)-xq*cos(t)+yq*sin(t)+xq;
yn=xp*sin(t)+yp*cos(t)-xq*sin(t)-yq*cos(t)+yq;
}
else
{
xn=xp*cos(t)+yp*sin(t)-xq*cos(t)-yq*sin(t)+xq;
yn=-xp*sin(t)+yp*cos(t)+xq*sin(t)-yq*cos(t)+yq;
}
printf("%0.lf %0.lf",xn,yn);
return 0;
}
This code gave correct output for both of the test cases provided in the question.
Do tell if it worked :)

Program to find Heat Index and Wind Chill (C Program)

I am having some trouble with the output of my program and can't figure out where I am going wrong. The Temperatures seem to be converting from celsius to Fahrenheit correctly, but when it comes to the the wind chill and heat index values, they are incorrect. This makes me think that something is wrong with the way I'm calculating them in my functions? If I could get an explanation to where my logic is wrong that would be great. Thanks in advance and sorry for my poor formatting!
#include <stdio.h>
#include <math.h>
#define L_Limit -20
#define U_Limit 50
#define c1 -42.379
#define c2 2.04901523
#define c3 10.14333127
#define c4 -0.22475541
#define c5 -6.83783E-3
#define c6 -5.481717E-2
#define c7 1.22874E-3
#define c8 8.5282E-4
#define c9 -1.99E-6
#define d1 35.74
#define d2 0.6125
#define d3 35.75
#define d4 0.4275
double compute_heat_index(int num1, int num2);
double compute_wind_chill(int num1, int num2);
double compute_heat_index(int num1, int num2)
{
int celsius;
double humid=.40;
double celsius_f=0, heat_index=0;
int ext1=0;
for(celsius=1;celsius<=num2;celsius++)
{
printf("%d\t", celsius);
celsius_f=(celsius*(9/5))+32;
printf("%2.2lf\t", celsius_f);
for(humid=.40;humid<=1;humid=humid+.10)
{
heat_index=c1+(c2*celsius_f)+(c3*humid)+. (c4*humid*celsius_f)+(c5*pow(celsius,2))+(c6*pow(humid,2))+(c7*pow(celsius,2)*humid)+(c8*celsius*pow(humid,2))+(c9*pow(celsius,2)*pow(humid,2));
if(heat_index<80)
printf("x\t");
else
printf("%2.2lf/t", heat_index);
}
if(celsius_f>100)
{
ext1++;
}
humid=.40;
celsius_f=0;
heat_index=0;
}
return heat_index;
}
double compute_wind_chill(int num1, int num2)
{
int celsius, wind=5;
double celsius_f=0, wind_chill=0;
int ext2=0;
for(celsius=1;celsius<=num2;celsius++)
{
printf("%d\t", celsius);
celsius_f=(celsius*(9/5))+32;
printf("%lf\t", celsius_f);
for(wind=5;wind<=40;wind=wind+5)
{
wind_chill=d1+(d2*celsius_f)-(d3*wind)+(d4*celsius_f*wind);
if(wind_chill>50)
printf("x\t");
else
printf("%lf\t", wind_chill);
}
if(celsius_f<-20)
{
ext2++;
}
wind=5;
celsius_f=0;
wind_chill=0;
}
return wind_chill;
}
int main(void)
{
double num1, num2;
int ext1=0, ext2=0;
printf("Input a range of values using two numbers:\n");
scanf("\n%lf%lf", &num1, &num2);
while(num1<L_Limit&&num1>U_Limit&&num2<L_Limit&&num2<U_Limit)
{
printf("Range of Values are Invalid!\n");
scanf("\n%lf%lf", &num1, &num2);
}
printf("Celsius\tFahrenheit\t5mph\t10mph\t15mph\t20mph\t25mph\t30mph\t35mph\t40mph\n");
compute_wind_chill(num1, num2);
printf("\nTotal Extreme Values: %d", ext1);
compute_heat_index(num1, num2);
printf("\nTotal Extreme Values: %d", ext2);
return 0;
}
While I make no comment on the correctness of your stoichiometric calculations (though I provide links and hints at the end), the following will help you find the problem, not only here, but hopefully in all future code you write as well. You are making things harder on yourself than they need be just by how you are formatting your code. Unless you are competing in a contest to see how few lines you can use, then for goodness sake, make things easier on yourself by 'opening up' you code a bit. This will make it much easier for you, and anyone helping you, to follow the logic of your code and find logic errors. For example, it is almost impossible to spot logic errors in:
heat_index=c1+(c2*celsius_f)+(c3*humid)+. (c4*humid*celsius_f)+(c5*pow(celsius,2))+(c6*pow(humid,2))+(c7*pow(celsius,2)*humid)+(c8*celsius*pow(humid,2))+(c9*pow(celsius,2)*pow(humid,2));
(of course your compiler will loudly complain about the errouneous '.' at the end of the first line)
It is much more readable written as:
heat_index = c1 + (c2 * celsius_f) + (c3 * humid) +
(c4 * humid * celsius_f) + (c5 * pow (celsius, 2)) +
(c6 * pow (humid, 2)) + (c7 * pow (celsius, 2) * humid) +
(c8 * celsius * pow (humid, 2)) +
(c9 * pow (celsius, 2) * pow (humid, 2));
or even:
heat_index = c1 +
(c2 * celsius_f) +
(c3 * humid) +
(c4 * humid * celsius_f) +
(c5 * pow (celsius, 2)) +
(c6 * pow (humid, 2)) +
(c7 * pow (celsius, 2) * humid) +
(c8 * celsius * pow (humid, 2)) +
(c9 * pow (celsius, 2) * pow (humid, 2));
NOTE: above you can easily see the misuse of celsius where celsius_f (Fahrenheit) should be used. Also note there is no need for pow (celsius_f, 2) where celsius_f * celsius_f will do the job.
Do the same for your output. Make it easy for you to read so it will be easier for others to read as well.
(I'm getting old and maybe your young-eyes have no trouble with code without spaces, it is much easier on me to help you if your code is adequately spaced and properly indented and your output looks like something other than spaghetti strung across the screen)
Avoid using 'magic numbers' in your code, e.g.
for(wind=5;wind<=40;wind=wind+5)
If you need constants in your code, declare them as required. That way, there is only one place you need to change the value, easily found at the top, instead of picking though your code to find them. You have declared a large number for your wet-bulb/dry-blub calculations, a few more for your limits is all that is required, e.g.
#define HMIN .40 /* define needed constants */
#define HMAX 1.0 /* avoid putting 'magic' */
#define HSTEP 0.1 /* numbers in your code */
#define WMIN 5
#define WMAX 40
#define WSTEP 5
...
for (wind = WMIN; wind <= WMAX; wind = wind + WSTEP)
Note: your HMIN, HMAX, HSTEP values will change when you correct your units (see last paragraph).
It appears you are wanting to return the values of ext1 and ext2 from your compute_wind_chill and compute_heat_index functions. If so, then your function type should match your return type needed. If you are wanting to indicate whether a extreme value was encountered by returning ext1 and ext2, then you should change your function type to int and assign the return to ext1 and ext2 in main, e.g.
int compute_heat_index (int num1, int num2);
int compute_wind_chill (int num1, int num2);
...
ext1 = compute_wind_chill (num1, num2);
printf ("\nTotal Extreme Values: %d\n", ext1);
...
ext2 = compute_heat_index (num1, num2);
printf ("\nTotal Extreme Values: %d\n", ext2);
Next, there is no need to make multiple calls to, e.g. printf when one will do. For example:
printf("%d\t", celsius);
celsius_f=(celsius*(9/5))+32;
printf("%2.2lf\t", celsius_f);
can be easily replaced with a single printf call just by logically ordering your celsius_f calculation, e.g.
celsius_f = (celsius * (9 / 5)) + 32;
printf ("%d\t% .2lf\t", celsius, celsius_f);
Why you declare num1 and num2 as double in main is a complete mystery. You pass them as int to your functions (where I assume num1 is supposed to be the lower loop value for temp in the functions instead of the hardcoded 1 you have). While you are free to allow users to enter e.g. 45.3 and read it as a double, and pass it as an int, it doesn't really make much logical sense. Here, the value of 45 is all that is ever used on your code. If you are reading as a double just to prevent error if a user enters 45.3, then that is a legitimate reason, but why a user would rather enter 45.3 instead of just 45 is another matter...
Your limit testing for values less/greater than L_Limit/U_Limit is a bit creative. It is better to simply put the values in ascending order to simplify the test, e.g.
/* VALIDATE all user input */
if (scanf ("%lf %lf", &num1, &num2) != 2) {
fprintf (stderr, "error: invalid input.\n");
return 1;
}
if (num1 > num2) { /* get values in ascending order */
double tmp = num1;
num1 = num2;
num2 = tmp;
}
while (num1 < L_Limit || num2 > U_Limit) { /* simple test */
Formatting your output is just something that takes a little more attention to detail. While I'm no fan of tab ('\t') formatting, I've made a quick attempt to clean things up a little to make the output more legible. Similarly, when you need an additional newline character, do not use the variadic printf ("\n");, there is no reason for the overhead just to output one character, use putchar ('\n'); instead. (note: you don't make that mistake, but I had to add a newline so it was worth mentioning here).
When you compile your code, always compile with warnings enabled, e.g. -Wall -Wextra in your compile string. You can add -pedantic for a few additional checks and there are a multitude of additional individual checks you can impose. Above all, do not accept code until it compiles cleanly, without warnings. Read the warnings you get. The compilers are quite good now at explaining exactly where the problem is and what you are doing wrong. (you can learn a lot of C, just by listening to what your compiler is telling you).
You can compile your code with something similar to the following:
$ gcc -Wall -Wextra -pedantic -std=gnu11 -Ofast -o bin/windchill windchill.c
Finally, putting it altogether, you could reformat your code and incorporate the changes above into something like the following that should make finding your stoichiometric logic error much easier. I have put my additional thoughts in the comments below:
#include <stdio.h>
#include <math.h>
#define L_Limit -20
#define U_Limit 50
#define c1 -42.379
#define c2 2.04901523
#define c3 10.14333127
#define c4 -0.22475541
#define c5 -6.83783E-3
#define c6 -5.481717E-2
#define c7 1.22874E-3
#define c8 8.5282E-4
#define c9 -1.99E-6
#define d1 35.74
#define d2 0.6125
#define d3 35.75
#define d4 0.4275
#define HMIN .40 /* define needed constants */
#define HMAX 1.0 /* avoid putting 'magic' */
#define HSTEP 0.1 /* number in your code */
#define WMIN 5
#define WMAX 40
#define WSTEP 5
/* you only need prototypes if you do not define your functions
* until AFTER the code that makes use of them. Moving the
* definitions AFTER main() makes the prototypes make sense,
* otherwise, just omit them...
*/
int compute_heat_index (int num1, int num2);
int compute_wind_chill (int num1, int num2);
int main (void) {
double num1 = L_Limit - 1.0, /* num1 & num2 should be int */
num2 = U_Limit + 1.0;
int ext1 = 0, ext2 = 0;
printf ("Input a range of temps in deg. C, (e.g. t1 t2): ");
/* VALIDATE all user input */
if (scanf ("%lf %lf", &num1, &num2) != 2) {
fprintf (stderr, "error: invalid input.\n");
return 1;
}
if (num1 > num2) { /* get values in ascending order */
double tmp = num1;
num1 = num2;
num2 = tmp;
}
while (num1 < L_Limit || num2 > U_Limit) { /* simple test */
fprintf (stderr, "error: values must be between %d - %d.\n",
L_Limit, U_Limit);
printf ("Input a range of temps in deg. C, (e.g. t1 t2): ");
if (scanf ("%lf %lf", &num1, &num2) != 2) {
fprintf (stderr, "error: invalid input.\n");
return 1;
}
}
/* make the output format easy to read */
printf ("\nDeg. C\t Deg. F\t 5mph\t 10mph\t 15mph\t"
" 20mph\t 25mph\t 30mph\t 35mph\t 40mph\n");
ext1 = compute_wind_chill (num1, num2);
printf ("\nTotal Extreme Values: %d\n", ext1);
printf ("\nDeg. C\t Deg. F\t 40%%\t 50%%\t 60%%\t"
" 70%%\t 80%%\t 90%%\t 100%%\n");
ext2 = compute_heat_index (num1, num2);
printf ("\nTotal Extreme Values: %d\n", ext2);
return 0;
}
/* comput and output heat index between num1 and num2 */
int compute_heat_index (int num1, int num2)
{
int celsius, ext1 = 0;
double humid = HMIN, celsius_f = 0, heat_index = 0;
for (celsius = num1; celsius <= num2; celsius++)
{
celsius_f = (celsius * (9 / 5)) + 32;
printf ("%d\t% .2lf\t", celsius, celsius_f);
for (humid = HMIN; humid <= HMAX; humid = humid + HSTEP)
{
heat_index = c1 + (c2 * celsius_f) + (c3 * humid) +
(c4 * humid * celsius_f) + (c5 * pow (celsius, 2)) +
(c6 * pow (humid, 2)) + (c7 * pow (celsius, 2) * humid) +
(c8 * celsius * pow (humid, 2)) +
(c9 * pow (celsius, 2) * pow (humid, 2));
if (heat_index < 80)
printf ("x\t");
else
printf ("% .2lf\t", heat_index);
}
putchar ('\n');
if (celsius_f > 100) {
ext1++;
}
}
return ext1;
}
/* comput and output wind chill between num1 and num2 */
int compute_wind_chill (int num1, int num2)
{
int celsius, wind = WMIN, ext2 = 0;
double celsius_f = 0, wind_chill = 0;
for (celsius = num1; celsius <= num2; celsius++)
{
celsius_f = (celsius * (9 / 5)) + 32;
printf ("%d\t% .2lf\t", celsius, celsius_f);
for (wind = WMIN; wind <= WMAX; wind = wind + WSTEP)
{
wind_chill = d1 + (d2 * celsius_f) - (d3 * wind) +
(d4 * celsius_f * wind);
if (wind_chill > 50)
printf (" x\t");
else
printf ("% .2lf\t", wind_chill);
}
putchar ('\n');
if (celsius_f < -20) {
ext2++;
}
}
return ext2;
}
Example Use/Output
$ ./bin/windchill
Input a range of temps in deg. C, (e.g. t1 t2): 45 55
error: values must be between -20 - 50.
Input a range of temps in deg. C, (e.g. t1 t2): 45 50
Deg. C Deg. F 5mph 10mph 15mph 20mph 25mph 30mph 35mph 40mph
45 77.00 x x 40.41 26.25 12.09 -2.07 -16.23 -30.40
46 78.00 x x 47.44 35.42 23.39 11.37 -0.66 -12.68
47 79.00 x x x 44.58 34.69 24.80 14.92 5.03
48 80.00 x x x x 45.99 38.24 30.49 22.74
49 81.00 x x x x x x 46.07 40.45
50 82.00 x x x x x x x x
Total Extreme Values: 0
Deg. C Deg. F 40% 50% 60% 70% 80% 90% 100%
45 77.00 99.68 99.21 98.74 98.27 97.80 97.32 96.85
46 78.00 101.06 100.58 100.10 99.61 99.13 98.65 98.17
47 79.00 102.43 101.93 101.44 100.95 100.46 99.96 99.47
48 80.00 103.78 103.28 102.78 102.27 101.77 101.27 100.76
49 81.00 105.13 104.61 104.10 103.59 103.07 102.56 102.04
50 82.00 106.46 105.93 105.41 104.89 104.36 103.84 103.31
Total Extreme Values: 0
note: one glaring error is your integer division error in your conversion to Fahrenheit. You can remedy that by insuring floating point division of your conversion factor:
celsius_f = (celsius * (9.0 / 5)) + 32;
Making that one change will have a dramatic impact on your calculations, e.g.
$ ./bin/windchill
Input a range of temps in deg. C, (e.g. t1 t2): 45 50
Deg. C Deg. F 5mph 10mph 15mph 20mph 25mph 30mph 35mph 40mph
45 113.00 x x x x x x x x
46 114.80 x x x x x x x x
47 116.60 x x x x x x x x
48 118.40 x x x x x x x x
49 120.20 x x x x x x x x
50 122.00 x x x x x x x x
Total Extreme Values: 0
Deg. C Deg. F 40% 50% 60% 70% 80% 90% 100%
45 113.00 170.20 168.93 167.65 166.37 165.09 163.81 162.53
46 114.80 173.15 171.84 170.54 169.23 167.92 166.61 165.30
47 116.60 176.09 174.75 173.42 172.08 170.74 169.40 168.06
48 118.40 179.01 177.65 176.28 174.92 173.55 172.18 170.81
49 120.20 181.92 180.53 179.14 177.74 176.35 174.95 173.56
50 122.00 184.82 183.40 181.98 180.55 179.13 177.71 176.28
Total Extreme Values: 0
You have some more work to do... You can start by reviewing The Heat Index Equation (which appears to be where your constants come from -- but note you are missing the correction factors and you need to pay careful attention to the units of humidity). Then follow up by looking at Wind Chill paying careful attention to the exponent on the wind. When you correct your formula, you will then need to link against the math library, so add -lm to your compile string. (that's little-'L'm). Once you correct your logic, you should see something similar to the following output.
(note: with the extreme values over a temperature range from -20 to 50, I get 164 wind_chill extremes and 332 heat_index extremes)
$ ./bin/windchill
Input a range of temps in deg. C, (e.g. t1 t2): 10 45
Wind Chill:
Deg. C Deg. F 5mph 10mph 15mph 20mph 25mph 30mph 35mph 40mph
10 50.00 47.77 45.59 44.19 43.15 42.31 41.59 40.98 40.43
11 51.80 49.87 47.80 46.48 45.50 44.70 44.02 43.44 42.92
12 53.60 51.96 50.02 48.77 47.84 47.09 46.45 45.90 45.41
13 55.40 54.06 52.23 51.06 50.19 49.48 48.88 48.36 47.90
14 57.20 56.16 54.45 53.35 52.53 51.87 51.31 50.82 50.39
15 59.00 58.26 56.66 55.64 54.88 54.26 53.74 53.28 52.88
16 60.80 60.36 58.88 57.93 57.22 56.65 56.16 55.74 55.37
17 62.60 62.45 61.09 60.22 59.57 59.04 58.59 58.21 57.86
18 64.40 x 63.30 62.51 61.91 61.43 61.02 60.67 60.35
19 66.20 x 65.52 64.80 64.26 63.82 63.45 63.13 62.85
20 68.00 x 67.73 67.09 66.60 66.21 65.88 65.59 65.34
21 69.80 x x 69.38 68.95 68.60 68.31 68.05 67.83
22 71.60 x x x 71.29 70.99 70.74 70.51 70.32
23 73.40 x x x x 73.38 73.16 72.98 72.81
24 75.20 x x x x x x x x
...
Total Extreme Values: 0
Heat Index:
Deg. C Deg. F 40% 50% 60% 70% 80% 90% 100%
...
26 78.80 x x x x x x x
27 80.60 80.35 81.35 82.55 83.94 85.53 87.32 89.31
28 82.40 81.80 83.21 85.01 87.20 89.78 92.75 96.10
29 84.20 83.49 85.39 87.86 90.91 94.53 98.74 103.51
30 86.00 85.44 87.89 91.10 95.07 99.80 105.29 111.55
31 87.80 87.64 90.71 94.72 99.68 105.58 112.42 120.21
32 89.60 90.10 93.85 98.73 104.74 111.86 120.11 129.49
33 91.40 92.81 97.32 103.13 110.25 118.66 128.38 139.39
34 93.20 95.77 101.11 107.92 116.20 125.97 137.21 149.92
35 95.00 98.99 105.22 113.09 122.61 133.78 146.60 161.07
36 96.80 102.46 109.65 118.65 129.47 142.11 156.57 172.84
37 98.60 106.18 114.40 124.60 136.78 150.95 167.10 185.24
38 100.40 110.16 119.47 130.93 144.54 160.30 178.20 198.26
39 102.20 114.39 124.87 137.65 152.75 170.15 189.87 211.90
40 104.00 118.88 130.58 144.76 161.40 180.52 202.11 226.17
41 105.80 123.62 136.62 152.25 170.51 191.40 214.91 241.05
42 107.60 128.61 142.98 160.13 180.07 202.79 228.28 256.56
43 109.40 133.85 149.66 168.40 190.08 214.68 242.22 272.70
44 111.20 139.35 156.66 177.06 200.53 227.09 256.73 289.45
45 113.00 145.10 163.99 186.10 211.44 240.01 271.81 306.83
Total Extreme Values: 97
Look things over and let me know if you have further questions.
Look here:
celsius_f=(celsius*(9/5))+32;
In C 9/5 is not equal to 9/5 as in real math, here integer divided by integer is equal to integer too, rounded to lower value. So here 9/5 is equal to 1, not 1.8. You should use float variable type, for example
celsius_f=(celsius*(9.0/5))+32;
Another mistake is here:
compute_wind_chill(num1, num2);
printf("\nTotal Extreme Values: %d", ext1);
You are displaying float result as integer.

Why doesn't this code for calculating the solution of quadratic equation not work?

Whenever I try running this, it returns the wrong solution, for example:
A: 303
B: 405
C: 50
Real solution: −0.13762776465722773
My solution : -110079.531250
#include <stdio.h>
#include <math.h>
int main(){
float a;
float b;
float c;
float solution;
float d;
printf("A: ");
scanf("%f", &a);
printf("B: ");
scanf("%f", &b);
printf("C: ");
scanf("%f",&c);
d = b * b - 4 * a * c;
solution = (-b - sqrt(d))/ 2*a;
printf("%f", solution);
}
You forgot BODMAS. Replace (-b - sqrt(d))/ 2*a by (-b - sqrt(d))/ (2*a)
solution = (-b - sqrt(d))/ (2*a);
Two things.
You need to watch out for the order of operations.
solution = (-b - sqrt(d)) / (2*a);
And depending on your customer you need to consider the accuracy of your result.
See "Avoiding loss of significance" for more information
And finally - i had a bit of fun writing my own version of your program:
#include <stdio.h>
#include <math.h>
void printLineSolution( double a, double b, double c );
int main()
{
printLineSolution(303,405,50);
printLineSolution(1,2,0);
printLineSolution(1,2,-1);
printLineSolution(1,-2,-3);
printLineSolution(1,-6,9);
printLineSolution(1,3,3);
getchar();
}
void printLineSolution( double a, double b, double c )
{
double d = (b * b) - (4 * a * c);
printf("(%lg)x^2 + (%lg)x + (%lg) = 0 ", a, b, c);
if( a == 0 )
{
printf("=> not quadratic");
}
else
{
if( 0 > d )
{
double r = - b / (2*a);
double i = sqrt( -d ) / (2*a);
printf("=> 2 complex: %lg + %lgi ; %lg - %lgi", r, i, r, i);
}
else if ( 0 == d )
{
double solution = - b / (2*a);
printf("=> 1 real: %lg", solution);
}
else
{
double s1 = (- b + sqrt( d ) ) / (2*a);
double s2 = (- b - sqrt( d ) ) / (2*a);
printf("=> 2 real: %lg ; %lg", s1, s2);
}
}
printf("\n");
}

Resources