Don Draper
Don Draper

Reputation: 541

Why do I get two different results? (issue with booleans)

I am a Python developer for the most part, but recently I have needed to solve a few problems using C and, honestly, it makes me suffer.

func.c

#define _CRT_SECURE_NO_WARNINGS

#define M_PI 3.1415926535897932384626433832795028841971693993751058209

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <math.h>
#include "Point.h"

bool point_on_line(struct Point p1, struct Point p2, struct Point point) {

    double min_x = min(p1.x, p2.x);
    double max_x = max(p1.x, p2.x);
    double min_y = min(p1.y, p2.y);
    double max_y = max(p1.y, p2.y);

    if (p2.y - p1.y == 0) {
        return point.y == p2.y && point.x >= min_x && point.x <= max_x && point.y >= min_y && point.y <= max_y;
    }

    if (p2.x - p1.x == 0) {
        return point.x == p2.x && point.x <= max_x && point.x >= min_x && point.y >= min_y && point.y <= max_y;
    }

    double k = (p2.y - p1.y) / (p2.x - p1.x);
    double b = (p2.x * p1.y - p1.x * p2.y) / (p2.x - p1.x);

    return point.y == (k * point.x + b) && point.x >= min_x && point.x <= max_x && point.y >= min_y && point.y <= max_y;
}

double calculate_angle(struct Point p1, struct Point p2) {

    double dot_product = p1.x * p2.x + p1.y * p2.y;

    double lenp1 = sqrt(p1.x * p1.x + p1.y * p1.y);

    double lenp2 = sqrt(p2.x * p2.x + p2.y * p2.y);

    double orientation = p1.x * p2.y - p1.y * p2.x;

    int sign;

    if (orientation > 0) {
        sign = 1;
    }
    else {
        sign = -1;
    }

    return sign * acos(dot_product / (lenp1 * lenp2));
}

bool check_border(struct Point p, struct Point points[], int size) {

    for (int i = 0; i < size - 1; i++) {

        if (point_on_line(points[i], points[i + 1], p)) {

            return true;
        }
    }

    return false;
}

bool calc_angle_sum(struct Point p1, struct Point points[], int size) {

    struct Point* vectors = malloc(size * sizeof(struct Point));

    for (int i = 0; i < size; i++) {

        struct Point temp = { points[i].x - p1.x,points[i].y - p1.y };
        vectors[i] = temp;
    }

    double total_sum = 0;

    for (int i = 0; i < size - 1; i++) {
        total_sum += calculate_angle(vectors[i], vectors[i + 1]);
    }

    bool res = (fabs(total_sum - 2 * M_PI)) < 0.00005;

    printf("TOTAL SUM %.100f\n", total_sum);

    printf("DIFFERENCE SMALL %d\n", fabs(total_sum - 2 * M_PI) < 0.00005);

    return fabs(total_sum - 2 * M_PI) < 0.00005;

    //return res;
}

Source.c

#define _CRT_SECURE_NO_WARNINGS
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "Point.h"

int main() {

    int length = 5;

    struct Point p1 = { 1,2 };
    struct Point p2 = { 5,0 };
    struct Point p3 = { 7,4 };
    struct Point p4 = { 5,6 };
    struct Point p5 = { 2,5 };
    struct Point p6 = { 1,2 };

    struct Point points_test[6] = {p1,p2,p3,p4,p5,p6};

    struct Point point_test = {7,3};

    //bool result = calc_angle_sum(point, points, length + 1);

    //printf("%s", result ? "true\n" : "false\n");

    if (check_border(point_test, points_test, length + 1)) {

        printf("BORDER");
        return 0;
    }

    else if (calc_angle_sum(point_test, points_test, length + 1)) {

        printf("INSIDE");
        return 0;
    }

    else {
        printf("OUTSIDE");
        return 0;
    }

}

Point.h


#pragma once

struct Point {
    double x, y;
};

coordinates.txt

1 2 5 0 7 4 5 6 2 5

lap.txt (the first number is the number of rectangle vertices, the second and third - the coordinates of the point.

5 7 3

This algorithm determines whether a point is inside/outside/on an edge of a given polygon using the winding number method.

The point (7,3) (the second and third numbers inside lap.txt) lies outside the polygon so the correct answer is "OUTSIDE/FALSE". Nevertheless, the output differs depending on Debug/Release and the way I return from calc_angle_sum function.

When I return this way:

return fabs(total_sum - 2 * M_PI) < 0.00005;

I get inconsistent results depending on debug/release mode.

The following way, however, seems to work fine:

bool res = (fabs(total_sum - 2 * M_PI)) < 0.00005
return res

Below is the part inside Source.c that calls the method:

else if (calc_angle_sum(point, points, length + 1)) {

        printf("INSIDE");
        return 0;
    }

There is something I cannot understand about how expressions are evaluated in C.

In Python, I am used to returning like return <some_expression> and expect it to get converted to True/False. In C, however, this doesn't seem to be true, or else there is some other error.

Upvotes: 0

Views: 125

Answers (1)

One obvious problem is that of implicit function declarations.

Neither

bool calc_angle_sum(struct Point p1, struct Point points[], int size)

and

bool check_border(struct Point p, struct Point points[], int size)

are not declared in the translation unit source.c. Therefore the compiler assumes that the functions are of type

int calc_angle_sum()
int check_border()

Were the return type of the functions int, they could be called compatibly in this manner - with these arguments. But because the actual return type of the functions is bool, the behaviour of the function calls is undefined.

C99 removed implicit function definitions. A compliant C99, C11, C17 compiler must complain about these function calls in your source.c.But the substandard MSVC compiler barely meets the long obsolete C89 specification...

Thus, try declaring

bool calc_angle_sum(struct Point p1, struct Point points[], int size);
bool check_border(struct Point p, struct Point points[], int size);

in Point.h.

Upvotes: 2

Related Questions