Существует ли простой способ преобразовать угол (в градусах), чтобы быть между-179 и 180? Я уверен, что мог использовать модификацию (%) и некоторые, если операторы, но это становится ужасным:
//Make angle between 0 and 360
angle%=360;
//Make angle between -179 and 180
if (angle>180) angle-=360;
Просто кажется, что должна быть простая математическая операция, которая сделает оба оператора одновременно. Мне, вероятно, просто придется создать статический метод для преобразования на данный момент.
Я немного опаздываю вечеринке, я знаю, но...
Большинство этих ответов не являются хорошими, потому что они стараются быть умными и лаконичными, а затем не заботятся о крайних случаях.
Это немного более подробно, но если вы хотите, чтобы это сработало, просто заложите логику, чтобы это сработало. Не пытайся быть умным.
int normalizeAngle(int angle) { int newAngle = angle; while (newAngle <= -180) newAngle += 360; while (newAngle > 180) newAngle -= 360; return newAngle; }
Это работает и является достаточно чистым и простым, не пытаясь быть модным. Обратите внимание, что можно выполнить только ноль или один из циклов while.
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;
Попробуйте это вместо этого!
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!)
Как насчет
(angle % 360) - 179
Это фактически вернет результаты, отличные от наивного подхода, представленного в вопросе, но сохранит угол между указанными границами. (Я полагаю, это может сделать это неправильным ответом, но я оставлю его здесь, если он решит аналогичную проблему другого человека).
// 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;
найти. | grep -v\.svn
Оказалось, что это не так сложно, как я это делал.
Я изменил это:
$form->field_name->addMultiOption('value', ' • label');
На это:
$form->field_name->addMultiOption('value',
html_entity_decode(' •', ENT_COMPAT, 'UTF-8') . ' label');
-121--4746120- Может быть, не полезно, но мне всегда нравилось использовать углы без градуса.
Диапазон углов от 0 до 255 может поддерживаться в пределах с помощью побитовых операций или для однобайтовой переменной, простой для переполнения.
Диапазон углов от -128 до 127 не очень прост при использовании побитовых операций, но для однобайтовой переменной можно разрешить ее переполнение.
Я думал, что это была отличная идея много лет назад для игр, где вы, вероятно, используете таблицу поиска углов. В наши дни не так хорошо - углы используются по-разному, и все равно плавают.
Все еще - может, стоит упомянуть.
Краткий способ работы с отрицательными числами -
double mod = x - Math.floor((x + 179.0) / 360) * 360;
Привести по вкусу.
Кстати: похоже, что углы между (180,0, 181,0) не определены. Разве диапазон не должен быть (-180, 180] (исключительный, включительно)
Тоже не так умно, но нет, если.
angle = (angle + 179)% 360 - 179;
Но я не уверен, как Java обрабатывает по модулю отрицательные числа. Это работает, только если -1 по модулю 360 равно 359.
ОБНОВЛЕНИЕ
Только что проверил документы и a% b
дает значение между - (| b | - 1)
и + (| b | - 1)
следовательно код нарушен . Чтобы учесть отрицательные значения, возвращаемые оператором по модулю, необходимо использовать следующее.
angle = ((angle + 179) % 360 + 360) % 360 - 179;
Но ... нет ... никогда ... Используйте что-то похожее на ваше первоначальное решение, но фиксированное для значений меньше -179.