Als C-Programmierer und C # -Programmierer mag ich an C # nicht, wie ausführlich mathematische Funktionen sind. Jedes Mal, wenn Sie beispielsweise eine Sinus-, Cosinus- oder Potenzfunktion verwenden müssten, müssten Sie der statischen Math-Klasse voranstellen. Dies führt zu sehr langem Code, wenn die Gleichung selbst ziemlich einfach ist. Das Problem wird noch schlimmer, wenn Sie Datentypen typisieren müssen. Infolgedessen leidet meiner Meinung nach die Lesbarkeit. Beispielsweise:
double x = -Math.Cos(X) * Math.Sin(Z) + Math.Sin(X) * Math.Sin(Y) * Math.Cos(Z);
Im Gegensatz zu einfach
double x = -cos(X) * sin(Z) + sin(X) * sin(Y) * cos(Z);
Dies ist auch in anderen Sprachen wie Java der Fall.
Ich bin nicht sicher, ob diese Frage tatsächlich eine Lösung hat, aber ich würde gerne wissen, ob es Tricks gibt, mit denen C # oder Java-Programmierer die Lesbarkeit von Math-Code verbessern können. Mir ist jedoch klar, dass C # / Java / etc. Da es sich nicht um mathematisch orientierte Sprachen wie MATLAB oder ähnliches handelt, ist dies sinnvoll. Aber gelegentlich müsste man immer noch mathematischen Code schreiben, und es wäre großartig, wenn man ihn lesbarer machen könnte.
quelle
using System.Math; … double x = -Cos(X) * Sin(Z) + Sin(X) * Sin(Y) * Cos(Z);
.Antworten:
Sie können lokale Funktionen definieren, die die globalen statischen Funktionen aufrufen. Hoffentlich integriert der Compiler die Wrapper und der JIT-Compiler erstellt dann einen engen Assembler-Code für die tatsächlichen Vorgänge. Beispielsweise:
Sie können auch Funktionen erstellen, die allgemeine mathematische Operationen in einzelne Operationen bündeln. Dies würde die Anzahl der Instanzen verringern , in denen Funktionen wie
sin
undcos
in Ihrem Code erscheinen, wodurch die clunkiness der globalen statischen Funktionen weniger auffällig aufrufen. Beispielsweise:Sie arbeiten auf der Ebene von Punkten und Rotationen, und die zugrunde liegenden Triggerfunktionen sind vergraben.
quelle
In Java stehen viele Tools zur Verfügung, um bestimmte Dinge weniger ausführlich zu gestalten. Sie müssen sich lediglich ihrer bewusst sein. In diesem Fall ist der
static
Import nützlich ( Tutorial-Seite , Wikipedia ).In diesem Fall,
läuft ganz gut ( ideone ). Es ist etwas umständlich, einen statischen Import der gesamten Math-Klasse durchzuführen, aber wenn Sie viel Mathe ausführen, kann dies erforderlich sein.
Mit dem statischen Import können Sie ein statisches Feld oder eine statische Methode in den Namespace dieser Klasse importieren und aufrufen, ohne den Paketnamen zu benötigen. Sie finden dies häufig in Junit-Testfällen, in denen
import static org.junit.Assert.*;
alle Asserts verfügbar sind.quelle
public interface Constants { final static public double PI = 3.14; }
und dannpublic class Foo implements Constants
, um Zugriff auf die Konstanten in der Benutzeroberfläche zu erhalten. Dies machte ein großes Durcheinander. Daher wurde mit 1.5 der statische Import hinzugefügt, um das Abrufen bestimmter Konstanten und statischer Funktionen zu ermöglichen, ohne eine Schnittstelle implementieren zu müssen.import static java.lang.Math.cos;
Mit C # 6.0 können Sie die Funktion des statischen Imports verwenden.
Ihr Code könnte sein:
Siehe: Statische Using-Anweisungen (AC # 6.0-Sprachvorschau)
BEARBEITEN: Seit der Veröffentlichung von Visual Studio 2015, CTP im Januar 2015, ist für den statischen Import ein explizites Schlüsselwort erforderlich
static
. mögen:quelle
Zusätzlich zu den anderen guten Antworten hier kann ich auch eine DSL für Situationen mit erheblicher mathematischer Komplexität empfehlen (keine durchschnittlichen Anwendungsfälle, aber möglicherweise einige finanzielle oder akademische Projekte).
Mit einem DSL-Generierungstool wie Xtext können Sie Ihre eigene vereinfachte mathematische Grammatik definieren, die wiederum eine Klasse mit der Java-Darstellung (oder einer anderen Sprache) Ihrer Formeln generiert.
DSL-Ausdruck:
Erzeugte Ausgabe:
In einem solch einfachen Beispiel lohnen sich die Vorteile der Erstellung der Grammatik und des Eclipse-Plugins nicht. Bei komplizierteren Projekten kann dies jedoch große Vorteile bringen, insbesondere wenn die DSL es Geschäftsleuten oder akademischen Forschern ermöglicht, formelle Dokumente in einem komfortablen Format zu verwalten und seien Sie versichert, dass ihre Arbeit korrekt in die Implementierungssprache des Projekts übersetzt wurde.
quelle
In C # können Sie Erweiterungsmethoden verwenden.
Das Folgende liest sich ziemlich gut, wenn man sich an die "Postfix" -Notation gewöhnt hat:
Leider macht die Rangfolge der Operatoren den Umgang mit negativen Zahlen hier etwas hässlicher. Wenn Sie
Math.Cos(-X)
stattdessen rechnen möchten, müssen-Math.Cos(X)
Sie die Zahl in Klammern setzen:quelle
x.Sin()
Ich würde einige Anpassungen vornehmen, aber ich missbrauche Erweiterungsmethoden und dies wäre persönlich meine erste Neigung.C #: Eine Variation von Randall Cooks Antwort , die mir gefällt, weil sie das mathematische "Aussehen" des Codes mehr beibehält als Erweiterungsmethoden, ist die Verwendung eines Wrappers, aber die Verwendung von Funktionsreferenzen für die Aufrufe, anstatt sie zu umbrechen. Ich persönlich denke, dass der Code dadurch sauberer aussieht, aber im Grunde ist es dasselbe.
Ich habe ein kleines LINQPad-Testprogramm gestartet, das Randalls umschlossene Funktionen, meine Funktionsreferenzen und die direkten Aufrufe enthält.
Die funktionsbezogenen Anrufe dauern grundsätzlich genauso lange wie die direkten Anrufe. Die umschlossenen Funktionen sind durchweg langsamer - wenn auch nicht um ein Vielfaches.
Hier ist der Code:
Ergebnisse:
quelle
Benutze Scala! Sie können symbolische Operatoren definieren und benötigen keine Parens für Ihre Methoden. Dies macht Mathe Weise leichter zu interpretieren.
Die gleiche Berechnung in Scala und Java könnte beispielsweise so aussehen:
Das summiert sich ziemlich schnell.
quelle