Thread: Strange issue: Different results of the calculation of a polygn area and perimeter

  1. #1
    Registered User
    Join Date
    Dec 2016
    Posts
    7

    Strange issue: Different results of the calculation of a polygn area and perimeter

    Im have a program to calculate the area and perimeter of a polygn. Also Im confiming if the result of the area and perimeter calculations are equal to the expected result.

    I dont understand what is happening but the verification part, to confirm if the area and perimeter are equal to what it is expected is not working corretly.

    For exemple, I test now and I get that "Arrays are the same" in all cases, which is correct because I gave the correct coordinates in the txt file to match each one of the expected results. But I test a little bit later or on a diferente machine, I tested in Linux also, and in some cases it appears "Arrays are diferent". This is really strange to happen without changing the coordinates file or the code.

    Do you understand why this strange issue is happening?


    This is the texto file, with the correct coordinaes to mach the expected results:

    1.0 2.5 5.1 5.8 5.9 0.7
    1.2 4.1 5.1 5.8 6.8 1.9 2.9 0.2
    1.7 4.9 5.1 5.8 7.0 2.8 4.8 0.1 1.5 1.4
    2.1 5.3 5.1 5.8 7.0 3.5 5.9 0.7 2.9 0.2 1.0 2.5
    2.5 5.6 5.1 5.8 6.9 3.9 6.5 1.3 4.2 0.0 1.8 1.0 1.0 3.4
    2.8 5.7 5.1 5.8 6.7 4.2 6.8 1.9 5.2 0.3 2.9 0.2 1.3 1.8 1.2 4.1

    Program:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <string.h>
    enum {x, y};
    typedef struct triangle {
        double v1[2];
        double v2[2];
        double v3[2];
    } triangle;
    double area(triangle a);
    double perimeter(double *vertices, int size);
    double side(double *p1, double *p2);
    
    char result[256];
    char expected[] = "11.7715.65";     //triangle regular
    char expected1[] = "18.1017.02";    //quadrilateral regular
    char expected2[] = "21.3317.60";    //pentagon regular
    char expected3[] = "23.5518.07";    //hexagon regular
    char expected4[] = "24.8018.29";    //heptagon regular
    char expected5[] = "25.1418.26";     //octagon regular
    
    int main()
    {
        int n, idx;
        int triangles;
        int index;
        int xycount;
        double xy;
        double triangle_area;
        double polygon_area;
        double perim;
        double polygon_vertices[50] = {0.0};
        triangle a;
        FILE* data;
        char line[256];
        char* token;
        if ((data = fopen("test.txt", "r")) == NULL) {
            fprintf(stderr, "can't open data file\n");
            exit (EXIT_FAILURE);
        }
        while (fgets(line, sizeof (line), data)){
            xycount = 0;
            polygon_area = 0;
            line[strlen(line) - 1] = 0;
            token = strtok(line, " ");
            while (token != NULL){
                xy = atof(token);
                token = strtok(NULL, " ");
                polygon_vertices[xycount++] = xy;
            }
            idx = 0;
            triangles = (xycount / 2) - 2;
            for (index = 2, idx = 0;idx < triangles;index += 2, ++idx){
                a.v1[x] = polygon_vertices[0];
                a.v1[y] = polygon_vertices[1];
                a.v2[x] = polygon_vertices[index + 0];
                a.v2[y] = polygon_vertices[index + 1];
                a.v3[x] = polygon_vertices[index + 2];
                a.v3[y] = polygon_vertices[index + 3];
                triangle_area = area(a);
                polygon_area += triangle_area;
            }
            printf("area=%.2f\t", polygon_area);
            perim = perimeter(polygon_vertices, xycount);
            printf("perimeter=%.2f\n", perim);
            sprintf(result, "%.2f%.2f", polygon_area, perim);
            if(strcmp(result,expected) == 0) {
                printf("Arrays are the same\n");
            }
            else if(strcmp(result,expected1) == 0){
                printf("Arrays are the same\n");
            else if(strcmp(result,expected2) == 0){
                printf("Arrays are the same\n");        
            }
            else if(strcmp(result,expected3) == 0){
                printf("Arrays are the same\n");        
            }
            else if(strcmp(result,expected4) == 0){
                printf("Arrays are the same\n");        
            }
            else if(strcmp(result,expected5) == 0){
                printf("Arrays are the same\n");
            }
            else {
                printf("Arrays are the different\n");        
            }
        }
        fclose(data);
        return 0;
    }
    /* calculate triangle area with Heron's formula */
    double area(triangle a)
    {
        double s1, s2, s3, S, area;
        s1 = side(a.v1, a.v2);
        s2 = side(a.v2, a.v3);
        s3 = side(a.v3, a.v1);
        S = (s1 + s2 + s3) / 2;
        area = sqrt(S*(S - s1)*(S - s2)*(S - s3));
        return area;
    }
    /* calculate polygon perimeter */
    double perimeter(double *vertices, int size)
    {
        int idx, jdx;
        double p1[2], p2[2], pfirst[2], plast[2];
        double perimeter;
        perimeter = 0.0;
        /* 1st vertex of the polygon */
        pfirst[x] = vertices[0];
        pfirst[y] = vertices[1];
        /* last vertex of polygon */
        plast[x] = vertices[size-2];
        plast[y] = vertices[size-1];
        /* calculate perimeter minus last side */
        for(idx = 0; idx <= size-3; idx += 2)
        {
            for(jdx = 0; jdx < 4; ++jdx)
            {
                p1[x] = vertices[idx];
                p1[y] = vertices[idx+1];
                p2[x] = vertices[idx+2];
                p2[y] = vertices[idx+3];
            }
            perimeter += side(p1, p2);
        }
        /* add last side */
        perimeter += side(plast, pfirst);
        return perimeter;
    }
    /* calculate length of side */
    double side(double *p1, double *p2)
    {
        double s1, s2, s3;
        s1 = (p1[x] - p2[x]);
        s2 = (p1[y] - p2[y]);
        s3 = (s1 * s1) + (s2 * s2);
        return sqrt(s3);
    }
    Last edited by chenb; 12-14-2016 at 06:19 PM.

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    You're converting numbers to strings and concatenating two of them together, then comparing strings; that's a pretty strange way to test whether some numbers are the same. Since you're summing up over floating point numbers, you may get different results on different machines. The Floating-Point Guide - What Every Programmer Should Know About Floating-Point Arithmetic It's best to use floating-point comparison with some error bound to see if your number is as expected...
    Code:
    #define EPSILON 1e-5
    if(fabs(observed - expected) < EPSILON) { /* ... */ }
    If you want comparisons that are independent of the magnitude of the values, you need to do something a little fancier: The Floating-Point Guide - Comparison

    P.S. You appear to be missing a line 72.5 (need a closing curly brace).
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Registered User
    Join Date
    Dec 2016
    Posts
    7
    Thanks for your answer. So if I compare doubles with doubles should work right? Because Im trying with the code below but now I get always that the arrays are diferent.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <string.h>
    enum {x, y};
    typedef struct triangle {
        double v1[2];
        double v2[2];
        double v3[2];
    } triangle;
    double area(triangle a);
    double perimeter(double *vertices, int size);
    double side(double *p1, double *p2);
    
    double expectedarea = 11.775000;     
    double expectedperimeter = 15.645596;     
    double expectedarea1 = 18.10;     
    double expectedperimeter1 = 17.02;     
    double expectedarea2 = 21.33;     
    double expectedperimeter2 = 16.60;     
    int main()
    {
        int idx;
        int triangles;
        int index;
        int xycount;
        double xy;
        double triangle_area;
        double polygon_area;
        double perim;
        double polygon_vertices[50] = {0.0};
        triangle a;
        FILE* data;
        char line[256];
        char* token;
        if ((data = fopen("test.txt", "r")) == NULL) {
            fprintf(stderr, "can't open data file\n");
            exit (EXIT_FAILURE);
        }
        while (fgets(line, sizeof (line), data)){
            xycount = 0;
            polygon_area = 0;
            line[strlen(line) - 1] = 0;
            token = strtok(line, " ");
            while (token != NULL){
                xy = atof(token);
                token = strtok(NULL, " ");
                polygon_vertices[xycount++] = xy;
            }
            idx = 0;
            triangles = (xycount / 2) - 2;
            for (index = 2, idx = 0;idx < triangles;index += 2, ++idx){
                a.v1[x] = polygon_vertices[0];
                a.v1[y] = polygon_vertices[1];
                a.v2[x] = polygon_vertices[index + 0];
                a.v2[y] = polygon_vertices[index + 1];
                a.v3[x] = polygon_vertices[index + 2];
                a.v3[y] = polygon_vertices[index + 3];
                triangle_area = area(a);
                polygon_area += triangle_area;
            }
            printf("area=%f\t", polygon_area);
            perim = perimeter(polygon_vertices, xycount);
            printf("perimeter=%f\n", perim);
    
            if(polygon_area == expectedarea && perim == expectedperimeter) {
                printf("Arrays are the same");
            }
            if(polygon_area == expectedarea1 && perim == expectedperimeter1) {
                printf("Arrays are the same");
            }
            if(polygon_area == expectedarea2 && perim == expectedperimeter2) {
                printf("Arrays are the same");
            }
            
            else {
                printf("Arrays are the different");        }
        }
        fclose(data);
        return 0;
    }
    /* calculate triangle area with Heron's formula */
    double area(triangle a)
    {
        double s1, s2, s3, S, area;
        s1 = side(a.v1, a.v2);
        s2 = side(a.v2, a.v3);
        s3 = side(a.v3, a.v1);
        S = (s1 + s2 + s3) / 2;
        area = sqrt(S*(S - s1)*(S - s2)*(S - s3));
        return area;
    }
    /* calculate polygon perimeter */
    double perimeter(double *vertices, int size)
    {
        int idx, jdx;
        double p1[2], p2[2], pfirst[2], plast[2];
        double perimeter;
        perimeter = 0.0;
        /* 1st vertex of the polygon */
        pfirst[x] = vertices[0];
        pfirst[y] = vertices[1];
        /* last vertex of polygon */
        plast[x] = vertices[size-2];
        plast[y] = vertices[size-1];
        /* calculate perimeter minus last side */
        for(idx = 0; idx <= size-3; idx += 2)
        {
            for(jdx = 0; jdx < 4; ++jdx)
            {
                p1[x] = vertices[idx];
                p1[y] = vertices[idx+1];
                p2[x] = vertices[idx+2];
                p2[y] = vertices[idx+3];
            }
            perimeter += side(p1, p2);
        }
        /* add last side */
        perimeter += side(plast, pfirst);
        return perimeter;
    }
    /* calculate length of side */
    double side(double *p1, double *p2)
    {
        double s1, s2, s3;
        s1 = (p1[x] - p2[x]);
        s2 = (p1[y] - p2[y]);
        s3 = (s1 * s1) + (s2 * s2);
        return sqrt(s3);
    }

  4. #4
    Registered User
    Join Date
    May 2009
    Posts
    3,688
    Quote Originally Posted by chenb View Post
    Thanks for your answer. So if I compare doubles with doubles should work right?
    No, please re-read the post you are replying to!
    Edit: Remember to follow and read the links that was posted!

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 13
    Last Post: 12-14-2016, 02:12 PM
  2. Triangle Perimeter (nest structure)Issue
    By cc8163 in forum C++ Programming
    Replies: 1
    Last Post: 05-23-2016, 01:52 AM
  3. Replies: 4
    Last Post: 03-15-2013, 03:31 AM
  4. Replies: 6
    Last Post: 09-29-2011, 04:23 AM
  5. Area Perimeter
    By rossipoo in forum C Programming
    Replies: 5
    Last Post: 11-09-2010, 09:20 PM

Tags for this Thread