Obwohl es in Python einen solchen Operator gibt – **
, habe ich mich gefragt, warum Java und C ++ dies nicht tun auch eine.
Es ist einfach, eine für Klassen zu erstellen, die Sie in C ++ mit Operatorüberladung definieren (und ich glaube, dass dies auch in Java möglich ist), aber wenn Sie über primitive Typen wie int, double und sprechen usw. Sie müssen eine Bibliotheksfunktion wie Math.power
verwenden (und normalerweise beide in double umwandeln).
Warum also nicht einen solchen Operator definieren? für primitive Typen?
Kommentare
- In C ++ können wir keine eigenen Operatoren erstellen. Sie können nur die vorhandenen Operatoren überladen.
- @Mahesh, sodass ich meine eigene Zahlenklasse erstellen und den Operator ^ überladen kann, um eine Potenz zu sein. Das stimmt wirklich nicht.
- @RanZilber: Es ist wichtig, weil die Priorität des Operators
^
nicht mit der Priorität der Potenzierung übereinstimmt. Betrachten Sie den Ausdrucka + b ^ c
. In der Mathematik wird zuerst die Exponentiation durchgeführt (b ^ c
), dann wird die resultierende Potenz zua
addiert. In C ++ wird die Addition zuerst ausgeführt (a + b
), dann wird der Operator^
mitc
. Selbst wenn Sie den Operator^
so implementiert haben, dass er Potenzierung bedeutet, wird der Vorrang alle überraschen. - @RamZilber –
^
ist ein XOR in C ++. Es wird empfohlen, dass überladene Operatoren nicht anders vorgehen sollten, als ein primitiver Datentyp ihn verwendet. - @RanZilber: Da ‚ überhaupt nicht intuitiv zu bedienen ist Jeder dieser Operatoren, die Sie erwähnen, bedeutet Exponentiation. Ich würde ernsthaft die Kompetenz eines C ++ – Programmierers in Frage stellen, der den Operator
++
oder den Operator!
et. al. Exponentation bedeuten. Sie können jedoch trotzdem ‚ t, da die Operatoren, über die Sie sprechen, nur ein Argument akzeptieren. Die Potenzierung erfordert zwei Argumente.
Antwort
Im Allgemeinen sind die primitiven Operatoren in C (und in Erweiterung C ++) sind so konzipiert, dass sie mit einfacher Hardware in ungefähr einer einzigen Anweisung implementiert werden können. So etwas wie Potenzierung erfordert oft Softwareunterstützung. Daher ist es standardmäßig nicht vorhanden.
Außerdem wird es von der Standardbibliothek der Sprache in Form von std::pow
bereitgestellt.
Schließlich wäre dies für ganzzahlige Datentypen nicht sehr sinnvoll, da die meisten selbst kleinen Werte für die Potenzierung den für int erforderlichen Bereich von bis zu 65.535 ausblasen. Sicher, Sie könnten dies für Doubles und Floats tun, aber nicht ints, aber warum sollte die Sprache für eine selten verwendete Funktion inkonsistent sein?
Kommentare
- Während ich mit den meisten davon einverstanden bin, ist die Tatsache, dass der Modul Der Operator kann nicht für Gleitkommatypen verwendet werden. Dies ist für primitive Datentypen inkonsistent, aber auch dies wäre wahrscheinlich keine einzelne Anweisung auf einer Hardware, von der ich mir vorstellen kann, dass sie derzeit in irgendeiner Weise vorherrscht.
- @Sion: Zumindest auf x86, Modul ist eine einzelne Anweisung. (
DIV
führt sowohl Division als auch Modul aus.) ‚ hat mich jedoch zum Konsistenzpunkt gebracht. - @Billy ONeal: Gleitkomma-Modul lus in einer einzigen Anweisung? Ich habe ‚ in letzter Zeit nicht in der Versammlung herumgespielt, um es selbst zu wissen. Wenn dies der Fall ist, sollte der Moduloperator auf Gleitkomma-Typen anwendbar gemacht werden.
- @DonalFellows: FORTRAN hatte den Exponentiationsoperator lange zuvor Alles, was der Bignum-Unterstützung ähnelt.
- @DonalFellows: Ein Energieoperator ist ‚ bei ganzen Zahlen nicht so nützlich wie bei Floats, aber bei kleinen Potenzen (insbesondere beim Quadrieren) könnte dies der Fall sein haben definitiv seine Verwendung. Persönlich mag ich den Ansatz, Operatoren aus Buchstaben zu machen (wie Pascal es mit
div
oder FORTRAN mit.EQ.
tut); Abhängig von den Whitespace-Regeln der Sprache kann es möglich sein, eine beliebige Anzahl von Operatoren zu haben, ohne dass sie reservierte Wörter sein müssen.
Antwort
Diese Frage ist für C ++ zu beantworten: Stroustrup,“ Design and Evolution of C ++ „, beschreibt dies in Abschnitt 11.6.1, S. 247-250.
Es gab allgemeine Einwände gegen das Hinzufügen von a neuer Betreiber. Es würde die bereits überkomplizierte Prioritätstabelle ergänzen. Die Mitglieder der Arbeitsgruppe waren der Meinung, dass dies nur eine geringe Bequemlichkeit für eine Funktion bieten würde, und sie wollten manchmal in der Lage sein, ihre eigenen Funktionen zu ersetzen.
Es gab keinen guten Kandidaten für einen Bediener.^
ist exklusiv-or, und ^^
hat aufgrund der Beziehung zwischen &
und zu Verwirrung geführt |
und &&
und ||
. !
war ungeeignet, da die natürliche Tendenz bestand, !=
zur Potenzierung eines vorhandenen Werts zu schreiben, und dies wurde bereits angenommen. Das beste verfügbare war möglicherweise *^
, was anscheinend niemand wirklich mochte.
Stroustrup betrachtete **
erneut, aber es hat bereits eine Bedeutung in C: a**p
ist a
mal was auch immer p
zeigt auf und char ** c;
deklariert c
als Zeiger auf char
. Einführung von **
als Token, was „Deklaration eines Zeigers auf Zeiger auf“ bedeutet, „mal, worauf das nächste Ding zeigt“ (wenn es „ein Zeiger ist“) oder „Exponentiation“ (falls befolgt) durch eine Zahl) verursachte Vorrangprobleme. a/b**p
müsste als a/(b**p)
analysiert werden, wenn p eine Zahl wäre, aber (a/b) * *p
Wenn p ein Zeiger wäre, müsste dies im Parser aufgelöst werden.
Mit anderen Worten, es wäre möglich gewesen, aber es hätte die Prioritätstabelle und die Parser, und beide sind bereits zu kompliziert.
Ich kenne die Geschichte über Java nicht. Ich könnte nur spekulieren. Was C betrifft, wo es gestartet wurde, können alle C-Operatoren leicht in Assembly-Code übersetzt werden, teils um den Compiler zu vereinfachen, teils um zu vermeiden, dass zeitaufwändige Funktionen in einfachen Operatoren versteckt werden (die Tatsache, dass operator+()
und andere konnten große Komplexität verbergen und Leistungstreffer waren eine der ersten Beschwerden über C ++).
Kommentare
- Gute Antwort. Ich denke, Java hat versucht, C in dieser Hinsicht zu vereinfachen, also wollte niemand einen neuen Operator hinzufügen. Das ‚ ist schade, dass mich niemand gefragt hat, ich hätte sicherlich
*^
gern gehabt. : D - C wurde für die Textformatierung erstellt. Fortran wurde für Mathematik gebaut und hatte vor 20 Jahren komplexe Mathematik, Mathematik für Mathematik und Mathematik.
- @Martin Beckett: Können Sie Beweise dafür finden, dass C für die Textformatierung erstellt wurde? Es scheint mir eine sehr ungeschickte Sprache dafür zu sein, und was ich ‚ über den Ursprung von C gelesen habe, besagt, dass es hauptsächlich für die Systemprogrammierung für Unix entwickelt wurde.
- @DavidThornley – Es wurde entwickelt, um Unix zu schreiben, aber alle frühen Unix-Anwendungen scheinen Textformatierung gewesen zu sein, und für ‚ hat es eine umfangreiche Zeichenfolge und i / o Bibliothek.
- +1: Die vorhandene Bedeutung für
a**p
ist der Mörder. (Die Hacks, um dieses Problem zu umgehen … Brr!)
Antwort
Ich vermute Dies liegt daran, dass jeder von Ihnen eingeführte Operator die Komplexität der Sprache erhöht. Die Eintrittsbarriere ist daher sehr hoch. Ich verwende Exponentiation sehr, sehr selten – und ich bin mehr als glücklich, einen Methodenaufruf zu verwenden
Kommentare
- Jede Funktion beginnt mit -100 Punkten.
- Ich ‚ würde
x**2
undx**3
nicht so selten verwenden . Und eine magische Pow-Implementierung, die der Compiler kennt und für die einfachen Fälle optimiert, wäre schön. - @CodeInChaos:
x * x
undx * x * x
ist ‚ kein schlechter Ersatz für das Quadrat und den Würfel. - @David Sie können ‚ t schreibe einfach
x*x
, wenn x ein Ausdruck ist. Im besten Fall wird der Code unhandlich und im schlimmsten Fall langsamer oder sogar falsch. Sie müssen also ‚ Ihre eigenen Square- und Cube-Funktionen definieren. Und selbst dann wäre der Code hässlicher als die Verwendung von ** als Energieversorger. - @David Ich muss ja in Klammern setzen, aber ‚ muss nicht wiederholt werden der Ausdruck mehrmals und bläht den Quellcode auf. Das verringert die Lesbarkeit erheblich. Eine häufige Eliminierung von Unterausdrücken ist nur möglich, wenn der Compiler garantieren kann, dass der Ausdruck frei von Nebenwirkungen ist. Und zumindest .net Jitter ist in dieser Hinsicht nicht ‚ nicht zu klug.
Antwort
Die Designer der Java-Sprache und der Kernbibliothek haben beschlossen, die meisten mathematischen Operationen in die Klasse Math zu verlagern. Siehe Math.pow () .
Warum? Flexibilität, um Leistung vor Bit-für-Bit-Präzision zu priorisieren.Es würde gegen den Rest der Sprachspezifikation verstoßen, zu sagen, dass das Verhalten integrierter mathematischer Operatoren von Plattform zu Plattform variieren kann, während die Math-Klasse ausdrücklich angibt, dass das Verhalten möglicherweise die Präzision für die Leistung beeinträchtigt >
Im Gegensatz zu einigen numerischen Methoden der Klasse StrictMath sind alle Implementierungen der entsprechenden Funktionen der Klasse Mathematik ist nicht definiert, um die bitweise gleichen Ergebnisse zurückzugeben. Diese Entspannung ermöglicht leistungsfähigere Implementierungen, bei denen keine strikte Reproduzierbarkeit erforderlich ist.
Antwort
Die Potenzierung war von Anfang an Teil von Fortran, da sie direkt auf die wissenschaftliche Programmierung abzielte. Ingenieure und Physiker verwenden es häufig in Simulationen, da Potenzgesetzbeziehungen in der Physik üblich sind.
Python ist auch im wissenschaftlichen Rechnen stark vertreten (z. B. NumPy und SciPy). Dies, zusammen mit seinem Potenzierungsoperator, legt nahe, dass es auch auf wissenschaftliche Programmierung abzielte.
C, Java und C # haben Wurzeln in der Systemprogrammierung. Vielleicht ist dies ein Einfluss, der die Potenzierung aus der Gruppe der unterstützten Operatoren herausgehalten hat.
Nur eine Theorie.
Antwort
C definierte Operatoren nur für allgemeine arithmetische Operationen, auf die mit der ALU zugegriffen werden kann. Ihr Hauptziel war die Schaffung einer für Menschen lesbaren Schnittstelle zum Assembly-Code.
C ++ änderte kein Operatorverhalten, weil es alles wollte Die in C geschriebene Codebasis ist kompatibel.
Java hat dasselbe getan, weil es vorhandene C ++ – Programmierer nicht einschüchtern wollte.
Kommentare
- Bei der Erstellung von C fehlten Multiplikation und Division nicht selten an Hardware und mussten in Software implementiert werden. C verfügt jedoch über Multiplikations- und Divisionsoperatoren.
- @siride: Meines Wissens hatte der PDP-7, der erste Computer, auf dem Unix ausgeführt wurde, Hardware-Multiplikation und -Division über seine EAE. Siehe: bitsavers.org/pdf/dec/pdp7/F-75_PDP-7userHbk_Jun65.pdf
Antwort
Nun, weil jeder Operator, der für eine Leistung sinnvoll wäre, bereits verwendet wird. ^ ist XOR und ** definiert einen Zeiger auf einen Zeiger. Stattdessen haben sie nur eine Funktion, die dasselbe tut. (wie pow ())
Kommentare
- @RTS – Sucht ein Sprachentwickler wirklich mehr nach Sinn als nach Effizienz?
Ein guter Entwickler einer Programmiersprache betrachtet beides. Ich kann ‚ nichts über Java sagen. In c ++ wird die Funktion pow () jedoch zur Kompilierungszeit berechnet. Und ist genauso effizient wie die regulären Operatoren.
pow()
führt ihre Berechnung zur Laufzeit durch, es sei denn, Sie haben einen Compiler, der eine konstante Faltung durchführen kann für pow()
, was ich sehr bezweifle. (Einige Compiler bieten Ihnen jedoch die Möglichkeit, Prozessor-Intrinsics für die Berechnung zu verwenden.) *
ist ein lexikalisches Token, unabhängig davon, ob es ‚ zur Indirektion oder Multiplikation verwendet wird. Ein **
bedeutet, dass Exponentiation entweder ein oder zwei lexikalische Token ist, und Sie möchten wirklich nicht, dass Ihr Lexer das Symbol treffen muss. ‚ Tabelle zum Tokenisieren. Antwort
Fakt ist, arithmetische Operatoren sind nur Verknüpfungen von Funktionen. (Fast) Alles, was Sie mit ihnen machen, kann mit einer Funktion gemacht werden. Beispiel:
c = a + b; // equals c.set(a.add(b)); // or as free functions set(c, add(a,b));
Es ist nur ausführlicher, daher sehe ich nichts Falsches daran, Funktionen zu verwenden, um „Potenz von“ auszuführen.
Antwort
Addition / Subtraktion / Negation und Multiplikation / Division sind grundlegende mathematische Operatoren. Wenn Sie Potenz zu einem Operator machen würden, wo würden Sie aufhören? Quadratwurzel Operator? N-Root-Operator? Logarithmus-Operator?
Ich kann nicht für ihre Schöpfer sprechen, aber ich kann sagen, dass ich denke, es wäre unhandlich und nicht orthogonal, solche Operatoren in der Sprache zu haben Die Anzahl der auf der Tastatur verbleibenden nicht alphanumerischen Zeichen / Leerzeichen ist eher begrenzt. Es ist seltsam, dass es in C ++ einen Moduloperator gibt.
Kommentare
- +1 – Ich ‚ verstehe nicht, warum es seltsam ist,
mod
als Operator zu haben. Es ‚ ist normalerweise eine einzelne Anweisung. ‚ ist eine primitive Operation für ganze Zahlen. Es ‚ wird in der Informatik am häufigsten verwendet.(Das Implementieren von Dingen wie begrenzten Puffern ohnemod
würde stinken.) - @Billy ONeal: Seltsam wegen der Inkonsistenz zwischen der Verwendung mit Ganzzahltypen und Gleitkommatypen . Absolut nützlich und ich würde ‚ nicht davon träumen, es zu entfernen. Nur schrullig ist alles.