Como programador de C y programador de C #, una de las cosas que no me gusta de C # es cuán detalladas son las funciones matemáticas. Cada vez que tendría que usar una función Sin, coseno o potencia, por ejemplo, tendría que anteponer la clase estática Math. Esto lleva a un código muy largo cuando la ecuación en sí es bastante simple. El problema empeora aún más si necesita escribir tipos de datos. Como resultado, en mi opinión, la legibilidad sufre. Por ejemplo:
double x = -Math.Cos(X) * Math.Sin(Z) + Math.Sin(X) * Math.Sin(Y) * Math.Cos(Z);
A diferencia de simplemente
double x = -cos(X) * sin(Z) + sin(X) * sin(Y) * cos(Z);
Este es también el caso en otros idiomas como Java.
No estoy seguro de si esta pregunta realmente tiene una solución, pero me gustaría saber si hay algún truco que C # o los programadores de Java usan para mejorar la legibilidad del código matemático. Sin embargo, me doy cuenta de que C # / Java / etc. no son lenguajes orientados a las matemáticas como MATLAB o similares, por lo que tiene sentido. Pero de vez en cuando uno todavía necesitaría escribir código matemático y sería genial si pudiera hacerlo más legible.
fuente
using System.Math; … double x = -Cos(X) * Sin(Z) + Sin(X) * Sin(Y) * Cos(Z);
.Respuestas:
Puede definir funciones locales que llaman a las funciones estáticas globales. Con suerte, el compilador incluirá los envoltorios, y luego el compilador JIT producirá un código de ensamblaje ajustado para las operaciones reales. Por ejemplo:
También puede crear funciones que agrupen operaciones matemáticas comunes en operaciones individuales. Esto minimizaría la cantidad de instancias en las que las funciones aparecen
sin
ycos
aparecen en su código, lo que hace que la dificultad de invocar las funciones estáticas globales sea menos notable. Por ejemplo:Está trabajando a nivel de puntos y rotaciones, y las funciones trigonométricas subyacentes están enterradas.
fuente
Dentro de Java, hay muchas herramientas disponibles para hacer que ciertas cosas sean menos detalladas, solo hay que tenerlas en cuenta. Uno que es útil en este caso es el de la
static
importación ( página de tutorial , wikipedia ).En este caso,
corre bastante bien ( ideone ). Es un poco pesado hacer una importación estática de todos la clase de Matemáticas, pero si está haciendo muchas matemáticas, entonces podría ser necesario.
La importación estática le permite importar un campo o método estático en el espacio de nombres de esta clase e invocarlo sin requerir el nombre del paquete. A menudo encuentras esto en los casos de prueba de Junit donde
import static org.junit.Assert.*;
se encuentra para obtener todas las afirmaciones disponibles.fuente
public interface Constants { final static public double PI = 3.14; }
y luegopublic class Foo implements Constants
en todas las clases para obtener acceso a las constantes en la interfaz. Esto hizo un gran desastre. Entonces, con 1.5, se agregó la importación estática para permitir la extracción de constantes específicas y funciones estáticas sin tener que implementar una interfaz.import static java.lang.Math.cos;
Con C # 6.0 puede usar la función de importación estática.
Tu código podría ser:
Consulte: Declaraciones de uso estático (Vista previa del lenguaje AC # 6.0)
EDITAR: desde Visual Studio 2015, CTP lanzado en enero de 2015, la importación estática requiere una palabra clave explícita
static
. me gusta:fuente
Además de las otras buenas respuestas aquí, también podría recomendar un DSL para situaciones con una complejidad matemática sustancial (no casos de uso promedio, pero tal vez algunos proyectos financieros o académicos).
Con una herramienta de generación de DSL como Xtext , puede definir su propia gramática matemática simplificada, que a su vez podría generar una clase que contenga la representación Java (o cualquier otro lenguaje) de sus fórmulas.
Expresión DSL:
Salida generada:
En un ejemplo tan simple, los beneficios de crear la gramática y el complemento de Eclipse no valdrían la pena, pero para proyectos más complicados, podría generar grandes beneficios, especialmente si el DSL permitiera a los empresarios o investigadores académicos mantener documentos formales en un ambiente cómodo. lenguaje, y tenga la seguridad de que su trabajo fue traducido con precisión al lenguaje de implementación del proyecto.
fuente
En C # podría usar métodos de extensión.
Lo siguiente se lee bastante bien una vez que te acostumbras a la notación "postfix":
Desafortunadamente, la precedencia del operador hace que las cosas sean un poco más feas cuando se trata de números negativos aquí. Si desea calcular en
Math.Cos(-X)
lugar de-Math.Cos(X)
, deberá encerrar el número entre paréntesis:fuente
x.Sin()
tomaría algún ajuste, pero abuso de los métodos de extensión y esta sería, personalmente, mi primera inclinaciónC #: Una variación de la respuesta de Randall Cook , que me gusta porque mantiene el "aspecto" matemático del código más que los métodos de extensión, es usar un contenedor pero usar referencias de función para las llamadas en lugar de ajustarlas. Personalmente, creo que hace que el código se vea más limpio, pero básicamente está haciendo lo mismo.
Abrí un pequeño programa de prueba LINQPad que incluía las funciones ajustadas de Randall, mis referencias de funciones y las llamadas directas.
Las llamadas a las que se hace referencia a la función básicamente toman el mismo tiempo que las llamadas directas. Las funciones ajustadas son consistentemente más lentas, aunque no en gran medida.
Aquí está el código:
Resultados:
fuente
Use Scala! Puede definir operadores simbólicos y no necesita parens para sus métodos. Esto hace que las matemáticas manera más fácil de interpretar.
Por ejemplo, el mismo cálculo en Scala y Java podría ser algo como:
Esto se suma bastante rápido.
fuente