Like Tree1Likes
  • 1 Post By anduril462

please help !!

This is a discussion on please help !! within the C Programming forums, part of the General Programming Boards category; Hello. This is a very simple program for calculating some parameters of a triangle and at first it seems to ...

  1. #1
    Registered User
    Join Date
    Oct 2011
    Location
    Prague, Czech Republic, Czech Republic
    Posts
    15

    please help !!

    Hello. This is a very simple program for calculating some parameters of a triangle and at first it seems to be working fine. The problem is though, I do get wrong output for some tricky values. So for example if the input is a=1.3847, b=0.2497 and c=1.362 the output tells me it is an acute triangle which is not true. The program recognizes one of the cosine values to be 0 but still doesn't tell me it is a right triangle ... Any idea what am I missing ??

    Much appreciated!

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #define M_PI 3.14159265358979323846
    
    
    int main(int argc, char** argv) {
    
    
    double a,b,c;
    
    
        printf("Enter side lengths a, b and c:\n");
    
    
        if(scanf("%lf%lf%lf",&a,&b,&c)!=3||a<=0||b<=0||c<=0)
        {
            printf("\nInvalid input.\n");
            printf("You may not enter non-numeric and 0 or negative values.\n");
            return 0;
        }
        else
        {
            /* measurement of the angles in radians and degrees */
            double cos_A=(b*b+c*c-a*a)/(2*b*c);
            double cos_B=(a*a+c*c-b*b)/(2*a*c);
            double cos_C=(a*a+b*b-c*c)/(2*a*b);
            double rad_A=acos(cos_A);
            double rad_B=acos(cos_B);
            double rad_C=acos(cos_C);
            double pi=M_PI;
            double deg_A=acos(cos_A)*(180/pi);
            double deg_B=acos(cos_B)*(180/pi);
            double deg_C=acos(cos_C)*(180/pi);
            
                   
            if (a+b>c&&a+c>b&&b+c>a)
            {
                if (a==b&&b==c)
                {
                    printf("The triangle is equilateral.\n");
                }
                else if (a==b||a==c||b==c)
                {
                    printf("The triangle is isosceles.\n");
                }
                else
                {
                    printf("The triangle is scalene.\n");
                }
                if (cos_A==0||cos_B==0||cos_C==0)
                {
                    printf("The triangle is a right triangle.\n");
                }
                else if (deg_A>90||deg_B>90||deg_C>90)
                {
                    printf("The triangle is obtuse.\n");
                }
                else
                {
                    printf("The triangle is acute.\n");
                }
            }
            else
            {
                printf("The triangle does not exist.\n");
                return 0;
            }
        }
        return 0;
    }

  2. #2
    Registered User TheBigH's Avatar
    Join Date
    May 2010
    Location
    Melbourne, Australia
    Posts
    426
    Due to truncation effects, it is not a good idea to test two floating point numbers for equality. You should set a small tolerance, like this:

    Code:
    if( a==b ) printf( "Yay!\n" ); /* WRONG */
    if( a-b < EPSILON ) printf( "Woohoo!\n" ); /* BETTER */
    And the triangle you mentioned actually is acute; it's almost an isosceles triangle with two long sides and a short one so all its angles will be less than 90.
    Code:
    while(!asleep) {
       sheep++;
    }

  3. #3
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,427
    Floating point representation is inaccurate in computers. Print out the values of cos_A, cos_B and cos_C, to 20 or so decimal places, and see what you get (add these lines):
    Code:
    printf("cos_A = %.20lf, cos_B = %.20lf, cos_C = %.20lf\n", cos_A, cos_B, cos_C);
    printf("rad_A = %.20lf, rad_B = %.20lf, rad_C = %.20lf\n", rad_A, rad_B, rad_C);
    printf("deg_A = %.20lf, deg_B = %.20lf, deg_C = %.20lf\n", deg_A, deg_B, deg_C);
    You need to check for "close enough to zero", not "exactly zero". Read this article for more info: What Every Computer Scientist Should Know About Floating-Point Arithmetic.

    Also, you don't need the following line, just use M_PI in your equations.
    Code:
    double pi=M_PI;
    TheBigH likes this.

  4. #4
    Registered User
    Join Date
    Oct 2011
    Location
    Prague, Czech Republic, Czech Republic
    Posts
    15
    Thank you for your replies. I actually guessed there would be something wrong with floating point numbers but I couldn't figure out the solution. The 'small tolerance' solution is great. Thanks again ...

  5. #5
    Registered User
    Join Date
    Oct 2011
    Location
    Prague, Czech Republic, Czech Republic
    Posts
    15
    Thanks for the reply. Actually the program was much longer and I was calculating the area and other stuff as well. Except for the above-mentioned part I was not running on any other error, so for the sake of readability I cut off some of the lines .... and forgot to remove the Pi thing Anyway, thanks a lot ...

  6. #6
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,427
    Quote Originally Posted by Andi Rrashi View Post
    Thank you for your replies. I actually guessed there would be something wrong with floating point numbers but I couldn't figure out the solution. The 'small tolerance' solution is great. Thanks again ...
    Do note that you need a small modification to TheBigH's solution, specifically you need to use fabs (if not, and if a >> b, then you would get a false positive):
    Code:
    if (fabs(a - b) < EPSILON)
        // numbers are "equal"

Popular pages Recent additions subscribe to a feed

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21