Как «переполнить» значение вне определенного диапазона (например, 30 - 100) - PullRequest
0 голосов
/ 29 января 2019

Я создал структуру "Range", которая содержит два целых числа, называемых min и max.Я пытаюсь написать функцию, которая принимает целое число и переполняет его, если оно выходит за пределы диапазона.Например, если у меня есть диапазон 1-100 и я передаю 105, возвращаемое значение должно быть 5.

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

Это структура диапазона, которую я использую

struct Range
{
    int min;
    int max;
};

И это объявление функциикоторый я использую для кода ниже

int overflowRange(const Range &range, int n)

Вот код, когда значение выходит за пределы диапазона. max

if (n > range.max)
{
    double dist = static_cast<double>(n - range.max);
    double length = (range.max - range.min) + 1;
    //How many ranges away is n ?
    double numRanges = std::ceil(dist / length);

    return static_cast<int>(n - (length * numRanges));
}

А вот код, когда значение выходит за пределы диапазона.мин

else if (n < range.min)    //n is the tested integer
{
    double dist = static_cast<double>(range.min - n);
    double length = (range.max - range.min);
    //How many ranges away is n ?
    int numRanges = static_cast<int>(dist / length);

    return static_cast<int>((range.min + length) - (dist - (length * numRanges)));
}

, когда dist / length == 1 или length * numRanges == dist, возвращаемое значение иногда выходит за пределы диапазона.

Например: если диапазон равен 30-100, а целое число равно -40Я ожидаю, что возвращаемое значение будет 30, но на самом деле оно 100.

Ответы [ 3 ]

0 голосов
/ 29 января 2019

Ваша проблема, по-видимому, связана с неявным использованием max в качестве базовых данных, когда значение ниже min.Если вы измените выражение return на следующее, оно должно работать.

return static_cast<int>(n + length*numRanges); // similar to above range case

Вы могли бы упростить логику, позволив математике позаботиться о направлении, в то время как вы просто позаботились о системе координат.

int numRanges = 0;
double length = range.max - range.min; // you could make this a function on Range
if (n < range.min)
{
   double dist = n - range.min;
   numRanges = std::floor(dist/length);
}
else if (n > range.max)
{
   double dist = n - range.max;
   numRanges = std::ceil(dist/length);
}
else
{
   numRanges = 0;
}

return value - numRanges * length;

Я протестировал этот алгоритм с [-40, 29, 30, 100, 101, 170], и результаты были [30, 99, 30, 100, 31, 100] соответственно.

0 голосов
/ 29 января 2019

Согласно вашему примеру, учитывая диапазон 1 - 100, возвращаемое значение должно быть 5, когда вы передаете 105, вы используете 100 в качестве 0 в диапазоне 101 - 200. Это означает, что длина вашего диапазона равна 100но не 99, потому что вы на самом деле переполняете 100 номеров.Так что здесь вы используете длину = (range.max - range.min) + 1, но не (range.max - range.min).

Но когда значение проходного значения ниже минимального, какова ваша"ожидаемое поведение"?Например, учитывая диапазон 30-100, какое число должно быть возвращено, когда вы передаете в 29?Согласно вашему исключению: «Если диапазон составляет 30–100, а целое число - 40, я ожидаю, что возвращаемое значение будет 30», тогда оно должно вернуть 30+ (29 - (- 40)) = 99 при 29, что означаетчто 30 и 100 представляют собой одно и то же число.Следовательно, в этом примере вы переполняете 69 чисел, но не 70, это означает, что вы здесь используете length = (range.max - range.min).Здесь конфликт случается!Вы не должны изменять длину диапазона следующим образом!

0 голосов
/ 29 января 2019

Вы можете решить это с помощью целочисленной математики:

struct Range
{
    int min;
    int max;
};

int overflowRange(const Range &range, int n)
{
    int size = range.max - range.min;
    n -= range.min;
    n %= size;
    if (n < 0)
    {
        n += size;
    }
    n += range.min;
    return n;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...