c++ - actividad fisica definicion
Escriba las operaciones de fĂsica segura en C++ (9)
¿Tiene sentido en C ++ definir unidades de física como tipos separados y definir operaciones válidas entre esos tipos?
Absolutamente. La biblioteca estándar de Chrono ya hace esto para puntos de tiempo y duraciones.
¿Hay alguna ventaja en la introducción de muchos tipos y mucha sobrecarga del operador en lugar de utilizar simplemente valores de coma flotante para representarlos?
Sí: puede usar el sistema de tipos para detectar errores, como agregar una masa a una distancia en tiempo de compilación, sin agregar ninguna sobrecarga de tiempo de ejecución.
Si no tiene ganas de definir los tipos y operadores usted mismo, Boost tiene una biblioteca de unidades para eso.
¿Tiene sentido en C ++ definir unidades de física como tipos separados y definir operaciones válidas entre esos tipos?
¿Hay alguna ventaja en la introducción de muchos tipos y mucha sobrecarga del operador en lugar de utilizar simplemente valores de coma flotante para representarlos?
Ejemplo:
class Time{...};
class Length{...};
class Speed{...};
...
Time operator""_s(long double val){...}
Length operator""_m(long double val){...}
...
Speed operator/(const Length&, const Time&){...}
Donde el Time
, la Length
y la Speed
se pueden crear como un tipo de devolución de diferentes operadores?
Di una presentación de tutorial en CPPcon 2015 en la biblioteca de Boost.Units. Es una potente biblioteca que todas las aplicaciones científicas deberían usar. Pero es difícil de usar debido a la escasa documentación. Espero que mi tutorial me ayude con esto. Puede encontrar las diapositivas / código here:
He pasado por este camino. Las ventajas son todas las numerosas y buenas ventajas normales de seguridad tipo. Las desventajas que me he encontrado:
- Querrá guardar los valores intermedios en los cálculos ... como los segundos al cuadrado. Tener estos valores como un tipo es algo sin sentido (segundos ^ 2 obviamente no es un tipo como la
velocity
). - Querrá hacer cálculos cada vez más complejos que requerirán más y más sobrecargas / definir operador para lograr.
Al final del día, es extremadamente limpio para cálculos simples y propósitos simples. Pero cuando las matemáticas se complican, es difícil que un sistema de unidades tipeadas funcione bien.
No estoy diciendo que estés equivocado al hacerlo, pero nos hemos pasado de la raya con eso en el proyecto en el que estoy trabajando y francamente dudo que sus beneficios superen sus problemas. Particularmente si estás en un equipo, una buena asignación de nombres variables (solo deletrear las malditas cosas), revisiones de códigos y pruebas unitarias evitarán cualquier problema. Por otro lado, si puede usar Boost, las unidades pueden ser algo para registrar (no lo he hecho).
Para aquellos que buscan una poderosa biblioteca de unidades de tipo compilable en tiempo de compilación, pero dudan acerca de cómo arrastrar en una dependencia de impulso, revisen las units . La biblioteca se implementa como un único archivo .h sin dependencias, y viene con un proyecto para construir pruebas / documentación de la unidad. Se ha probado con msvc2013, 2015 y gcc-4.9.2, y también debería funcionar con versiones posteriores de esos compiladores.
Divulgación completa: soy el autor de la biblioteca
Para verificar la seguridad del tipo, puede usar una biblioteca dedicada.
El uso más astuto es boost :: units, funciona perfectamente sin sobrecarga de tiempo de ejecución, muchas funciones. Si esta biblioteca teóricamente resuelve tu problema. Desde un punto de vista más práctico, la interfaz es tan incómoda y mal documentada que puede tener problemas. Además, el tiempo de compilación aumenta drásticamente con el número de dimensiones, por lo tanto, compruebe claramente que puede compilar en un tiempo razonable un proyecto grande antes de usarlo.
doc: http://www.boost.org/doc/libs/1_56_0/doc/html/boost_units.html
Una alternativa es usar unit_lite. Hay menos funciones que la biblioteca de impulso, pero la compilación es más rápida, la interfaz más simple y los mensajes de error son legibles. Esta lib requiere C ++ 11.
código: https://github.com/pierreblavy2/unit_lite
El enlace al documento se encuentra en la descripción de github (¡¡No puedo publicar más de 2 enlaces aquí !!!).
Realmente recomendaría boost.units para esto. Hace todo el tiempo de compilación de conversión y también le da un error de tiempo de compilación si está tratando de usar un ejemplo de código de error de dimensiones erróneas:
length l1, l2, l3;
area a1 = l1 * l2; // Compiles
area a2 = l1 * l2 * l3; // Compile time error, an area can''t be the product of three lengths.
volume v1 = l1 * l2 * l3; // Compiles
Sí, tiene sentido. No solo en física, sino en cualquier disciplina. En finanzas, por ejemplo, las tasas de interés están en unidades de intervalos de tiempo inversos (generalmente, expresos por año). El dinero tiene muchas unidades diferentes. La conversión entre ellos solo se puede hacer con una tasa cruzada, tiene dimensiones de una moneda divididas por otra. Los pagos de intereses, pagos de dividendos, pagos de capital, etc. normalmente ocurren con una frecuencia.
Puede evitar la multiplicación de dos valores y terminar con un valor ilegal. Puede evitar sumar dólares y euros, etc.
Todos han mencionado las garantías de seguridad tipo como un plus. Otro ENORME más es la capacidad de abstraer el concepto (longitud) de las unidades (metro).
Entonces, por ejemplo, un problema común al tratar con unidades es mezclar SI con métrica. Cuando los conceptos se abstraen como clases, ya no es un problema:
Length width = Length::fromMeters(2.0);
Length height = Length::fromFeet(6.5);
Area area = width * height; //Area is computed correctly!
cout << "The total area is " << area.toInches() << " inches squared.";
El usuario de la clase no necesita saber qué unidades utiliza la representación interna ... al menos, siempre que no haya problemas graves de redondeo.
Realmente me gustaría que más bibliotecas de trigonometría hicieran esto con ángulos, porque siempre tengo que buscar si esperan grados o radianes ...