Простой способ к хранению углов между-179 и 180 градусов

Существует ли простой способ преобразовать угол (в градусах), чтобы быть между-179 и 180? Я уверен, что мог использовать модификацию (%) и некоторые, если операторы, но это становится ужасным:


//Make angle between 0 and 360
angle%=360;

//Make angle between -179 and 180
if (angle>180) angle-=360;

Просто кажется, что должна быть простая математическая операция, которая сделает оба оператора одновременно. Мне, вероятно, просто придется создать статический метод для преобразования на данный момент.

36
задан User1 23 February 2010 в 19:16
поделиться

8 ответов

Я немного опаздываю вечеринке, я знаю, но...

Большинство этих ответов не являются хорошими, потому что они стараются быть умными и лаконичными, а затем не заботятся о крайних случаях.

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

int normalizeAngle(int angle)
{
    int newAngle = angle;
    while (newAngle <= -180) newAngle += 360;
    while (newAngle > 180) newAngle -= 360;
    return newAngle;
}

Это работает и является достаточно чистым и простым, не пытаясь быть модным. Обратите внимание, что можно выполнить только ноль или один из циклов while.

14
ответ дан 27 November 2019 в 05:09
поделиться
int angle = -394;

// shortest
angle %= 360;
angle = angle < -170 ? angle + 360 : (angle > 180 ? angle - 380 : angle);

// cleanest
angle %= 360;
if (angle < -179) angle += 360;
else if (angle > 180) angle -= 360;
1
ответ дан 27 November 2019 в 05:09
поделиться

Попробуйте это вместо этого!

atan2(sin(angle), cos(angle))

atan2 имеет диапазон [- π, π) . При этом используется тот факт, что tan θ = sin θ / cos θ , и что atan2 достаточно умен, чтобы знать, в каком квадранте θ находится.

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

atan2(sin(angle * PI/180.0), cos(angle * PI/180.0)) * 180.0/PI

Обновить Мой предыдущий пример был совершенно законным, но ограничивал диапазон до ± 90 °. Диапазон atan2 - требуемое значение от -179 ° до 180 °. Сохранилось ниже.


Попробуйте следующее:

asin(sin(angle)))

Область sin - это вещественная линия, диапазон - [- 1, 1] . Домен asin - [- 1, 1] , а диапазон - [- PI / 2, PI / 2] . Поскольку asin является инверсией sin , ваш ввод не изменяется (много, есть некоторый дрейф, потому что вы используете числа с плавающей запятой). Таким образом, вы получаете обратно свое входное значение и получаете желаемый диапазон как побочный эффект ограниченного диапазона арксинуса.

Поскольку вам нужны градусы, вам нужно преобразовать угол в радианы и обратно:

asin(sin(angle * PI/180.0)) * 180.0/PI

(Предостережение: триггерные функции в миллиард раз медленнее, чем простые операции деления и вычитания, даже если они выполняются в FPU!)

16
ответ дан 27 November 2019 в 05:09
поделиться

Как насчет

(angle % 360) - 179

Это фактически вернет результаты, отличные от наивного подхода, представленного в вопросе, но сохранит угол между указанными границами. (Я полагаю, это может сделать это неправильным ответом, но я оставлю его здесь, если он решит аналогичную проблему другого человека).

0
ответ дан 27 November 2019 в 05:09
поделиться
// reduce the angle  
angle =  angle % 360; 

// force it to be the positive remainder, so that 0 <= angle < 360  
angle = (angle + 360) % 360;  

// force into the minimum absolute value residue class, so that -180 < angle <= 180  
if (angle > 180)  
    angle -= 360;  
83
ответ дан 27 November 2019 в 05:09
поделиться

найти. | grep -v\.svn

-121--594819-

Оказалось, что это не так сложно, как я это делал.

Я изменил это:

$form->field_name->addMultiOption('value', '&nbsp;&bull; label');

На это:

$form->field_name->addMultiOption('value',
    html_entity_decode('&nbsp;&bull;', ENT_COMPAT, 'UTF-8') . ' label');
-121--4746120-

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

Диапазон углов от 0 до 255 может поддерживаться в пределах с помощью побитовых операций или для однобайтовой переменной, простой для переполнения.

Диапазон углов от -128 до 127 не очень прост при использовании побитовых операций, но для однобайтовой переменной можно разрешить ее переполнение.

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

Все еще - может, стоит упомянуть.

3
ответ дан 27 November 2019 в 05:09
поделиться

Краткий способ работы с отрицательными числами -

double mod = x - Math.floor((x + 179.0) / 360) * 360;

Привести по вкусу.

Кстати: похоже, что углы между (180,0, 181,0) не определены. Разве диапазон не должен быть (-180, 180] (исключительный, включительно)

3
ответ дан 27 November 2019 в 05:09
поделиться

Тоже не так умно, но нет, если.

angle = (angle + 179)% 360 - 179;

Но я не уверен, как Java обрабатывает по модулю отрицательные числа. Это работает, только если -1 по модулю 360 равно 359.

ОБНОВЛЕНИЕ

Только что проверил документы и a% b дает значение между - (| b | - 1) и + (| b | - 1) следовательно код нарушен . Чтобы учесть отрицательные значения, возвращаемые оператором по модулю, необходимо использовать следующее.

angle = ((angle + 179) % 360 + 360) % 360 - 179;

Но ... нет ... никогда ... Используйте что-то похожее на ваше первоначальное решение, но фиксированное для значений меньше -179.

9
ответ дан 27 November 2019 в 05:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: