Мод ближайший к нулю

У меня есть угол, и мне нужно вернуть репрезентативный угол в диапазоне [-180: 180].

Я написал функцию, чтобы сделать это, но это кажется таким простым процессом, Мне было интересно, если есть оператор или функция, которая уже сделала это:

int func(int angle){
angle %= 360;

if(angle > 180){
angle -=360;
}else if(angle < -180){
angle += 360;
}
return angle;
}

Я сделал живой пример для тестирования ожидаемой функциональности.

6

Решение

Код является оптимальным или, по крайней мере, почти так. Некоторые платформы могут работать лучше с некоторыми вариациями.

Нет ни одного целочисленного оператора C, который бы обрабатывал это.

Проблема заключается в том, что диапазон результатов [-180:180] и это 361 разных значений. Неясно, разрешено ли func(180) вернуть -180,

Следующая задача — заставить код работать над всем [INT_MIN...INT_MAX] диапазон как angle + 180 может переполниться. angle %= 360; заботится об этом.

Ниже приведен эффективный вариант кода OP, который может работать быстрее на машинах с конвейером. Это только один % операция — возможно самая дорогая. положительный angle возвращает [-179: 180] и отрицательный angle возвращает [-180: 179]

int func2(int angle) {
angle %= 360;
return angle + 360*((angle < -180) - (angle > 180));
}

Ниже приведен однострочник, который возвращает значения [-180: 179]. Не использует angle + 180 поскольку это может переполниться.

int func3(int angle) {
return ((angle % 360) + (360+180))%360 - 180;
}

Здесь <math.h> функция double remainder(double x, double y); это близко соответствует цели ОП. (Может быть доступно с C99.) Возвращает значения FP [-180: 180]. Замечания: int может иметь целочисленный диапазон, который превышает то, что double может представлять точно.

int func4(int angle) {
angle = remainder(angle, 360.0);
return angle;
}
3

Другие решения

Я не знаю стандартного оператора или функции, но вы можете сделать это в одном выражении:

int func(int angle) {
return ((((angle + 180) % 360) + 360) % 360) - 180;
}

Заметка: Мой оригинальный ответ использовал следующее выражение:

((angle + 180) % 360) - 180;

Это гораздо точнее, но полагается, что модуль отрицательного числа является положительным. Некоторые языки (такие как Python) имеют эту семантику, но C и C ++ обычно не имеют. Приведенное выше выражение объясняет это, добавляя дополнительный сдвиг на 360.

3

То, что вам нужно, это просто wrap реализация функции:

#include <stdio.h>

int wrap(int value, int lower_bound, int upper_bound) {
int range = upper_bound - lower_bound;
value -= lower_bound; // shift from [lower, upper) to [0, upper - lower)...
value %= range;       // ... so modulo operator could do all the job
if (value < 0) {      // deal with negative values
value += range;
}
value += lower_bound; // shift back to [lower, upper)
return value;
}

void show(int value, int lower_bound, int upper_bound) {
printf("%4d wrapped to the range of [%d, %d) is %d\n",
value, lower_bound, upper_bound,
wrap(value, lower_bound, upper_bound)
);
}

int main(void) {
// examples
show(0, -180, 180);
show(-200, -180, 180);
show(720, -180, 180);
show(1234, -180, 180);
show(5, 0, 10);
show(-1, 0, 10);
show(112, 0, 10);
show(-3, -10, 0);
show(7, -10, 0);
show(-11, -10, 0);
return 0;
}
1
По вопросам рекламы [email protected]