functions java math

functions - math.ceil java



Forma fácil de mantener ángulos entre-179 y 180 grados (15)

¡Prueba esto!

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

atan2 tiene un rango de [-π, π) . Esto aprovecha el hecho de que tan θ = sen θ / cos θ , y que atan2 es lo suficientemente inteligente como para saber en qué cuadrante θ se encuentra.

Como quiere grados, querrá convertir su ángulo hacia y desde radianes:

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

Actualización Mi ejemplo anterior era perfectamente legítimo, pero restringía el rango a ± 90 °. El rango de atan2 es el valor deseado de -179 ° a 180 °. Conservado abajo.

Prueba esto:

asin(sin(angle)))

El dominio del sin es la línea real, el rango es [-1, 1] . El dominio de asin es [-1, 1] , y el rango es [-PI/2, PI/2] . Como asin es el inverso del sin , tu entrada no cambia (mucho, hay un poco de deriva porque estás usando números en coma flotante). Así que recuperas el valor de entrada y obtienes el rango deseado como efecto secundario del rango restringido del arcoseno.

Como quiere grados, querrá convertir su ángulo hacia y desde radianes:

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

(Advertencia: las funciones Trig son millones de veces más lentas que las operaciones simples de dividir y restar, incluso si se realizan en una FPU).

¿Hay alguna manera fácil de convertir un ángulo (en grados) entre -179 y 180? Estoy seguro de que podría usar mod (%) y algunas declaraciones if, pero se pone feo:

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

Simplemente parece que debería haber una operación matemática simple que hará ambas declaraciones al mismo tiempo. Tal vez tenga que crear un método estático para la conversión por ahora.


Aquí está mi contribución. Parece que funciona para todos los ángulos sin problemas de borde. Es rápido. Puede hacer n180 [360000359] = -1 casi instantáneamente. Observe cómo la función Sign ayuda a seleccionar la ruta lógica correcta y permite usar el mismo código para diferentes ángulos.

Ratch

n180[a_] := If[Abs[Mod[a, If[Sign[a] == 0, 360, Sign[a] 360]]] <= 180, Mod[a, If[Sign[a] == 0, 360, Sign[a] 360]], Mod[a, If[Sign[a] == 0, 360, -Sign[a] 360]]]


Aquí hay una solución de entero solo:

int normalize(int angle) { angle %= 360; int fix = angle / 180; // Integer division!! return (fix) ? angle - (360 * (fix)) : angle; }

A veces ser inteligente es simplemente más divertido, Platinum Azure.


Bueno, una solución más, esta con una sola división y sin bucles.

static double normalizeAngle(double angle) { angle %= 360.0; // [0..360) if angle is positive, (-360..0] if negative if (angle > 180.0) // was positive return angle - 360.0; // was (180..360) => returning (-180..0) if (angle <= -180.0) // was negative return angle + 360.0; // was (-360..180] => returning (0..180] return angle; // (-180..180] }


Es mejor usar las funciones de la biblioteca. Manejan casos especiales como NaN e infinitos.

public static double normalizeAngleDegrees(double angle) { return Math.toDegrees(Math.atan2(Math.sin(Math.toRadians(angle)), Math.cos(Math.toRadians(angle)))); }


Esto funciona con números negativos y decimales y no requiere bucles, ni funciones trigonométricas:

ángulo - = Math.floor (ángulo / 360 + 0.5) * 360

El resultado está en el intervalo [-180, 180). Para el intervalo (-180, 180), puede usar esto en su lugar:

ángulo - = Math.ceil (ángulo / 360 - 0.5) * 360


He hecho una fórmula para la orientación de valores circulares

mantener el ángulo entre 0 y 359 es:

angle + Math.ceil( -angle / 360 ) * 360

pero para mantener entre -179 a 180 la fórmula puede ser:

angle + Math.ceil( (-angle-179) / 360 ) * 360

esto le dará a su orientación un cambio de -179 manteniendo el ángulo real intacto

La fórmula generalizada para cambiar la orientación del ángulo puede ser:

angle + Math.ceil( (-angle+shift) / 360 ) * 360


Llego un poco tarde a la fiesta, lo sé, pero ...

La mayoría de estas respuestas no son buenas, porque intentan ser inteligentes y concisas y luego no se ocupan de los casos extremos.

Es un poco más detallado, pero si quieres que funcione, solo agrega la lógica para que funcione. No intentes ser inteligente.

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

Esto funciona y es razonablemente limpio y simple, sin tratar de ser elegante. Tenga en cuenta que solo se pueden ejecutar cero o uno de los ciclos while.


Qué tal si

(angle % 360) - 179

Esto realmente arrojará resultados diferentes al enfoque ingenuo presentado en la pregunta, pero mantendrá el ángulo entre los límites especificados. (Supongo que podría hacer que esta sea la respuesta incorrecta, pero la dejaré aquí en caso de que resuelva el problema similar de otra persona).


Quizás no sea útil, pero siempre me gustó usar ángulos sin grados.

Un rango de ángulos de 0 a 255 se puede mantener dentro de los límites usando operaciones bit a bit, o para una variable de un solo byte, permitiendo el desbordamiento simple.

Un rango de ángulos de -128 a 127 no es tan fácil con operaciones bit a bit, pero de nuevo, para una variable de un solo byte, puede dejar que se desborde.

Pensé que era una gran idea hace muchos años para los juegos, donde probablemente estés usando una tabla de búsqueda para ángulos. En estos días, no tan bueno: los ángulos se utilizan de manera diferente, y flotan de todos modos.

Aún así, tal vez vale la pena mencionarlo.


Sé que han pasado años, pero aún así.

Esta solución no contiene bucles, no resta, no módulo (permite normalizar a intervalos de radianes). Funciona para cualquier entrada, incluidos valores negativos, valores grandes, casos extremos.

double normalizedAngle = angle - (ceil((angle + M_PI)/(2*M_PI))-1)*2*M_PI; // (-Pi;Pi]: double normalizedAngle = angle - (ceil((angle + 180)/360)-1)*360; // (-180;180]: double normalizedAngle = angle - (floor((angle + M_PI)/(2*M_PI)))*2*M_PI; // [-Pi;Pi): double normalizedAngle = angle - (floor((angle + 180)/360))*360; // [-180;180):


Una forma corta que maneja números negativos es

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

Echar al gusto

Por cierto: parece que los ángulos entre (180.0, 181.0) no están definidos. ¿No debería ser el rango de (-180, 180] (exclusivo, incluido)


No es tan inteligente, también, pero no si.

ángulo = (ángulo + 179)% 360 - 179;

Pero no estoy seguro de cómo maneja Java módulo para números negativos. Esto solo funciona si -1 módulo 360 es igual a 359.

ACTUALIZAR

Acabo de comprobar los documentos y a % b arroja un valor entre -(|b| - 1) y +(|b| - 1) por lo tanto, el código está roto . Para tener en cuenta los valores negativos devueltos por el operador de módulo, uno tiene que usar lo siguiente.

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

Pero ... no ... nunca ... Use algo similar a su solución inicial, pero fijo para valores menores a -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;


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;