написание функции, которая разбивает интервал в с - PullRequest
0 голосов
/ 19 декабря 2018

Я пишу функцию, которая должна увеличивать или уменьшать интервал между 1 и 100, в зависимости от того, какой параметр он принимает.

Он начинается с (0,100), затем, если parameter=-1, он становится(0,50), если parameter=1 впоследствии, оно становится (25, 50).Он хранит последнее «предположение» и дает следующее, основанное на этом.

Я хотел бы знать, что я делаю неправильно, когда parameter=-1 (часть, где предполагается уменьшить интервал).Другие части работают нормально, вам не нужно смотреть на них, они дают ожидаемый результат, НО этот (-1) дает 25 12 6 3 2 вместо 25 12 6 3 1.

вот код:

#include <stdio.h>

int NextGuess(int  param) {

    int num;
    static int a=1, b=99;

    //this part is where it goes wrong (the output doesn't match with the expected one)//
    if (param==-1) //less
    {
        b-=(a+b)/2 - a+1;
        num=(a+b)/2;
    }
    //these below are doing fine//

    if (param==1) //greater
    {
        a+=(a+b)/2 - a+1;
        num=(a+b)/2;
    }

    if (param==0) //equal
    num=(a+b)/2;

    return num;
}
//main isn't important, it's just for testing the output//
int main() {
printf ("%d ", NextGuess(-1));
printf ("%d ", NextGuess(-1));
printf ("%d ", NextGuess(-1));
printf ("%d ", NextGuess(-1));
printf ("%d ", NextGuess(-1));
//output should be: 25 12 6 3 1  but this gives: 25 12 6 3 2    
    return 0;
}

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

другие примеры того, чтоФункция должна выводиться при вызове:

printf ("%d ", NextGuess(1));
printf ("%d ", NextGuess(-1));
printf ("%d ", NextGuess(-1));
printf ("%d ", NextGuess(1));
//output: 75 62 56 59

Ответы [ 2 ]

0 голосов
/ 19 декабря 2018

Вместо того, чтобы критиковать, позвольте мне показать вам пару контрпримеров.Учитывайте следующее:

struct intrange {
    int   minimum;
    int   maximum;
};

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

struct intrange  intrange_split(const struct intrange  range,
                                const int              half)
{
    /* Midpoint of the range, rounding towards zero */
    const int        midpoint = (range.minimum + range.maximum) / 2;
    struct intrange  result;

    if (half > 0) {
        /* Upper half, including midpoint. */
        result.minimum = midpoint;
        result.maximum = range.maximum;
    } else
    if (half < 0) {
        /* Lower half, excluding midpoint. */
        result.minimum = range.minimum;
        result.maximum = midpoint - 1;
    } else {
        /* No change. */
        result = range;
    }

    return result;
}

. Вышеуказанная функция intrange_split() принимает в качестве параметра структуру intrange range и int half, чтобы указать, как ее разделить.Нет никаких проверок ошибок.

Если вы хотите работать со структурой, переданной по ссылке, вы можете использовать, скажем,

int intrange_split(struct intrange *range, int half)
{
    int midpoint;

    /* No range? Invalid range? */
    if (!range || range->maximum < range->minimum)
        return -1; /* Invalid range. */

    /* Note: This could overflow. */
    midpoint = (range->minimum + range->maximum) / 2;

    if (half == 1) {
        /* Upper half, including midpoint. */
        range->minimum = midpoint;
    } else
    if (half == -1) {
        /* Lower half, excluding midpoint. */
        range->maximum = midpoint - 1;
    } else {
        /* Invalid operation. */
        return -1;
    }

    /* Verify range is valid (non-empty). */
    if (range->maximum < range->minimum)
        return -1;

    /* Range is valid, and not empty. */
    return 0;
}

Более распространенное использование возвращаемого значения для представления успеха /ошибка в C, потому что в отличие от C ++, здесь нет исключений.(Вы также можете использовать утверждения или распечатать сообщение об ошибке и abort() или exit(EXIT_FAILURE), в зависимости от того, исправлена ​​ошибка или нет.)

Во всех вышеупомянутых случаях я использовал логику, согласно которой midpoint находится на полпути между minimum и maximum, округленными до нуля;и что midpoint принадлежит верхнему диапазону.Вы можете выбрать , как вы его определяете, если вы делаете выбор явно, и документировать его.Посмотрите, насколько проще эти подходы?

Также часто используют макросы препроцессора или статические встроенные функции для инициализации переменных.В этом случае, например,

#define  INTRANGE_INIT(min, max)  { min, max }

static inline struct intrange intrange_define(const int minimum,
                                              const int maximum)
{
    struct intrange  result = { minimum, maximum };
    return result;
}

, чтобы в своем коде вы могли объявить диапазон, используя, например, struct intrange my_range = INTRANGE_INIT(0, 100);.Конечно, вы можете также инициализировать его, используя struct intrange my_range = { 0, 100 }; или даже struct intrange my_range; my_range = intrange_define(0, 100);.

Пока реализация читаема и проста для понимания, это нормально.Я предпочитаю предпочитать стиль макроса препроцессора сам, но это чисто вопрос стиля.

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

(И никогда не привыкать думать, что вы добавите ошибкупроверка и обеспечение безопасности позже. Потому что вы не будете. Никто никогда не делает. Если они пытаются, они неизменно терпят неудачу. Это потому, что надежность и безопасность могут быть только разработаны, а не добавлены впоследствии.)

0 голосов
/ 19 декабря 2018

Давайте сделаем немного математики.Вы можете разбить математику на отдельные строки и пройти с помощью отладчика для подтверждения.

Для вызова, который возвращает предположение 2, ваши статические значения a == 1 и b == 6.

Таким образом, для (очищенного) кода

b-=(a+b)/2 - a + 1;
num=(a+b)/2;

мы получаем:

`a` + `b` == 7
7 / 2 == 3 (integer math)
3 - 1 + 1 == 3
6 - 3 == 3
num = (1 + 3) / 2 == 2

РЕДАКТИРОВАТЬ: Вот код, который возвращает желаемую последовательность.Не могу гарантировать, что я не нарушил вашу последовательность +1, хотя:)

int NextGuess(int  param) {
    int num;
    static int a=0, b=100;
    static int lastGuess = 50;

    //printf("%d %d %d %d\n", a, b, interval, lastGuess);
    if (param==-1) //less
    {
        b = lastGuess;
    }
    else if (param==1) //greater
    {
        a = lastGuess + 1;
    }

    lastGuess = (a+b) / 2;

    return lastGuess;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...