Почему я получаю два разных результата? (проблема с логическими значениями) - PullRequest
0 голосов
/ 06 ноября 2019

Я по большей части разработчик Python, но в последнее время мне нужно было решить несколько проблем с помощью C, и, честно говоря, это заставляет меня страдать.

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;
};

координаты.txt

1 2 5 0 7 4 5 6 2 5

lap.txt (первое число - число вершин прямоугольника, второеи третье - координаты точки.

5 7 3

Этот алгоритм определяет, находится ли точка внутри / снаружи / на краю заданного многоугольника, используя метод числа обмоток.

Точка(7,3) (второе и третье числа внутри lap.txt) лежат вне многоугольника, поэтому правильный ответ - "ВНЕ / ЛОЖЬ". Тем не менее, выходные данные различаются в зависимости от отладки / выпуска и способа возврата из функции calc_angle_sum.

Когда я возвращаюсь таким образом:

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

Я получаю противоречивые результаты в зависимости от режима отладки / выпуска.

Однако следующим способомкажется, работает нормально:

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

Ниже находится часть внутри Source.c, которая вызывает метод:

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

        printf("INSIDE");
        return 0;
    }

Есть кое-что, что я не могуне понимаю, как выражения оцениваются в C.

В Python я привык возвращать как return <some_expression> и ожидаю, что он будет преобразован в True/False. В Си, однако, это не так, иначе есть какая-то другая ошибка.

1 Ответ

2 голосов
/ 07 ноября 2019

Одной из очевидных проблем является проблема неявных объявлений функций.

Ни

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

, ни

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

не объявлены в единице перевода source.c. Поэтому компилятор предполагает, что функции имеют тип

int calc_angle_sum()
int check_border()

Если бы тип возвращаемых функций int, они могли бы быть вызваны таким образом совместимо с этими аргументами. Но поскольку фактический тип возвращаемых функций - bool, поведение вызовов функций - undefined .

C99 удалено неявное определение функции. Соответствующий компилятор C99, C11, C17 должен пожаловаться на эти вызовы функций в вашем source.c. Но некачественный компилятор MSVC едва соответствует давно устаревшей спецификации C89 ...

Таким образом, попробуйте , объявив

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

в Point.h.

...