Varför finns det ingen kraftoperatör i Java / C ++?

Även om det finns en sådan operatör – ** i Python undrade jag varför Java och C ++ inte har en också.

Det är enkelt att skapa en för klasser som du definierar i C ++ med operatörsöverbelastning (och jag tror att sådant är möjligt även i Java), men när man talar om primitiva typer som int, dubbel och så vidare måste du använda biblioteksfunktionen som Math.power (och vanligtvis måste du casta båda till dubbla).

Så – varför inte definiera en sådan operatör för primitiva typer?

Kommentarer

  • I C ++ kan vi inte skapa egna operatörer. Du kan bara överbelasta de befintliga operatörerna.
  • @Mahesh, så jag kan skapa min egen nummerklass och överbelasta ^ -operatören för att vara en kraft. Det verkar verkligen inte.
  • @RanZilber: Det spelar ingen roll eftersom operatören ^ inte överensstämmer med exponentieringens företräde. Tänk på uttrycket a + b ^ c. I matematik utförs exponentieringen först (b ^ c), sedan läggs den resulterande effekten till a. I C ++ utförs tillägget först (a + b) sedan utförs ^ operatören med c. Så även om du implementerade operatorn ^ för att betyda exponentiering, kommer företräde att överraska alla.
  • @RamZilber – ^ är en XOR i C ++. Det rekommenderas att överbelastad operatör inte ska göra annorlunda vad en primitiv datatyp gör med den.
  • @RanZilber: Eftersom den ’ inte alls är intuitiv att använda någon av de operatörer du nämner betyder exponentiering. Jag skulle allvarligt ifrågasätta kompetensen hos alla C ++ – programmerare som överbelastar ++ operatören eller ! operatören et. al. menar exponentation. Men du kan ’ t ändå, eftersom operatörerna du pratar om accepterar bara ett argument; exponentiering kräver två argument.

Svar

Generellt sett är de primitiva operatorerna i C (och i tillägg C ++) är utformade för att implementeras av enkel hårdvara i ungefär en enda instruktion. Något som exponentiering kräver ofta mjukvarusupport; så det är inte där som standard.

Det tillhandahålls också av språkets standardbibliotek i form av std::pow.

Slutligen skulle det inte vara mycket meningsfullt att göra detta för heltal datatyper, för de flesta till och med små värden för exponentiering blåser ut det intervall som krävs för int, det vill säga upp till 65 535. Visst, du kan göra detta för dubbel och flytande men inte ints, men varför göra språket inkonsekvent för en sällan använd funktion?

Kommentarer

  • Även om jag håller med om det mesta, faktumet att modulen operatören kan inte användas på flytande punkttyper är inkonsekvent för primitiva datatyper, men det skulle förmodligen inte vara en enda instruktion på någon hårdvara som jag föreställer mig är något utbrett nu.
  • @Sion: Åtminstone på x86, modul är en enda instruktion. (DIV gör både delning och modul) Du ’ har dock fått mig på konsistenspunkten.
  • @Billy ONeal: Floating point modu lus i en enda instruktion? Jag har inte ’ tuttat runt i församlingen för sent för att veta själv. Om så är ’, bör moduloperatorn göras tillämplig på flytande punkttyper.
  • @DonalFellows: FORTRAN hade exponentieringsoperatören långt innan den hade allt som liknar bignum-stöd.
  • @DonalFellows: En kraftoperatör är inte ’ t lika användbar med heltal som med flottör, men för små krafter (särskilt kvadrering) kan det definitivt har sina användningsområden. Personligen gillar jag tillvägagångssättet att göra operatörer av bokstäver (som Pascal gör med div eller FORTRAN med .EQ.); beroende på språkets blankstegsregler kan det vara möjligt att ha godtyckligt antal operatörer utan att kräva att de är reserverade ord.

Svar

Denna fråga är svarbar för C ++: Stroustrup,” Design och utveckling av C ++ ”diskuterar detta i avsnitt 11.6.1, s. 247-250.

Det fanns allmänna invändningar mot att lägga till en ny operatör. Det skulle lägga till den redan överkomplicerade prioritetstabellen. Medlemmarna i arbetsgruppen trodde att det skulle ge endast mindre bekvämlighet än att ha en funktion, och de ville ibland kunna ersätta sina egna funktioner.

Det fanns ingen bra kandidat för en operatör.^ är exklusivt eller, och ^^ bjöd in förvirring på grund av förhållandet mellan & | och && och ||. ! var olämpligt eftersom det skulle finnas den naturliga tendensen att skriva != för exponentiering av ett befintligt värde, och det har redan tagits. Det bästa tillgängliga kan ha varit *^, som ingen uppenbarligen gillade.

Stroustrup ansåg ** igen, men det har redan en mening i C: a**p är a gånger vad p pekar på, och char ** c; förklarar c som en pekare till pekare till char. Vi introducerar ** som en symbol som betyder ”deklaration av en pekare till pekare till”, ”gånger vad nästa sak pekar på” (om det är ”en pekare) eller” exponentiering ”(om följt med ett nummer) orsakade företräde problem. a/b**p skulle behöva analysera som a/(b**p) om p var ett nummer, men (a/b) * *p om p var en pekare, så detta måste lösas i parsern.

Med andra ord skulle det ha varit möjligt, men det skulle ha försvårat prioritetstabellen och parser, och båda är redan för komplicerade.

Jag vet inte historien om Java; allt jag kunde göra skulle vara att spekulera. När det gäller C, där det började, översätts alla C-operatorer enkelt till monteringskod, dels för att förenkla kompilatorn och dels för att undvika att dölja tidskrävande funktionalitet i enkla operatörer (det faktum att operator+() och andra kunde dölja stor komplexitet och prestationshits var ett av de tidiga klagomålen om C ++).

Kommentarer

  • Snyggt svar. Jag antar att Java försökte förenklas C i detta avseende, så ingen ville lägga till en ny operatör. Att ’ är synd att ingen frågade mig, jag skulle säkert ha velat *^. : D
  • C byggdes för att göra textformatering. Fortran byggdes för att göra matte och hade komplex matematik, kraft och matris 20 år tidigare.
  • @ Martin Beckett: Kan du hitta bevis för att C byggdes för textformatering? Det verkar för mig som ett väldigt klumpigt språk för det, och vad jag ’ har läst om ursprunget till C säger att det var designat för systemprogrammering för Unix främst.
  • @DavidThornley – Det var designat för att skriva Unix in, men alla de tidiga användningarna av Unix verkar ha varit textformatering och för den ’ s gång har den en omfattande sträng och jag / o bibliotek.
  • +1: Den befintliga betydelsen för a**p är mördaren. (Hackarna att lösa det problemet … Brr!)

Svar

Jag misstänker det beror på att varje operatör du introducerar ökar språkkomplexiteten. Inträdesbarriären är därför mycket hög. Jag använder mig av exponentiering väldigt, mycket sällan – och jag är mer än glad att använda en metod för att göra så.

Kommentarer

  • Varje funktion börjar med -100 poäng.
  • Jag ’ d använder x**2 och x**3 inte så sällan . Och en magisk pow-implementering som kompilatorn vet om och optimerar för de enkla fallen skulle vara trevligt.
  • @CodeInChaos: Men x * x och x * x * x aren ’ t dåliga ersättare för kvadrat och kub.
  • @ David kan du ’ t skriv helt enkelt x*x om x är ett uttryck. I bästa fall blir koden otymplig och i värsta fall långsammare eller till och med fel. Så du ’ d måste definiera dina egna Square- och Cube-funktioner. Och även då skulle koden vara fulare än att använda ** som kraftoperatör.
  • @ David Jag måste sätta parenteser ja, men behöver inte ’ inte behöver upprepa uttrycket flera gånger och sväller källkoden. Vilket minskar läsbarheten mycket. Och vanlig eliminering av subuttryck är endast möjlig om kompilatorn kan garantera att uttrycket är fritt från biverkningar. Och åtminstone .net jitter är inte ’ t för smart i det avseendet.

Svar

Java-språket och kärnbiblioteksdesignerna beslutade att förflytta de flesta matematiska operationer till klassen Math . Se Math.pow () .

Varför? Flexibilitet för att prioritera prestanda framför bit-för-bit-precision.Det skulle strida mot resten av språkspecifikationen att säga att beteendet hos inbyggda matematikoperatörer kan variera från plattform till plattform, medan matematikklassen specifikt säger att beteendet potentiellt offrar precision för prestanda, så köparen se upp:

Till skillnad från några av de numeriska metoderna i klass StrictMath , alla implementeringar av motsvarande funktioner i klass Matematik definieras inte för att returnera bit-för-bit-samma resultat. Denna avslappning möjliggör implementeringar med bättre prestanda där sträng reproducerbarhet inte krävs.

Svar

Exponentiering var en del av Fortran från början eftersom det riktades helt mot vetenskaplig programmering. Ingenjörer och fysiker använder det ofta i simuleringar, eftersom maktlagsförhållanden är vanliga inom fysik.

Python har också en stark närvaro inom vetenskaplig databehandling (t.ex. NumPy och SciPy). Detta, tillsammans med dess exponentieringsoperatör, antyder att det också var inriktat på vetenskaplig programmering.

C, Java och C # har rötter i systemprogrammering. Kanske är det ett inflytande som höll exponentiering utanför gruppen av operatörer som stöds.

Bara en teori.

Svar

C definierade operatörer endast för vanliga aritmetiska operationer som är tillgängliga med ALU. Dess huvudsyfte var att skapa ett mänskligt läsbart gränssnitt till församlingskod.

C ++ ändrade inte något operatörsbeteende eftersom det ville ha kodbasen skriven i C för att överensstämma.

Java gjorde detsamma eftersom den inte ville skrämma befintliga C ++ – programmerare.

Kommentarer

  • När C skapades saknades inte multiplicering och delning sällan hårdvara utan måste implementeras i programvara. Ändå har C multiplikations- och divisionsoperatörer.
  • @siride: Såvitt jag vet var PDP-7 den första datorn som körde Unix, hårdvarumultiplicering och delning genom sin EAE. Se: bitsavers.org/pdf/dec/pdp7/F-75_PDP-7userHbk_Jun65.pdf

Svar

Nåväl eftersom alla operatörer som skulle vara vettiga för en kraft redan används. ^ är XOR och ** definierar en pekare till en pekare. Så istället har de bara en funktion som gör samma sak. (som pow ())

Kommentarer

  • @RTS – Letar en språkutvecklare verkligen efter känsla mer än effektivitet?
  • En bra utvecklare av ett programmeringsspråk tittar på båda. Jag kan ’ inte säga något om java. Men i c ++ beräknas pow () -funktionen vid sammanställningstid. Och är lika effektiv som de vanliga operatörerna.
  • @RTS: pow() -funktionen utför sin beräkning vid körning, såvida du inte har en kompilator som kan göra konstant vikning för pow(), vilket jag tvivlar mycket på. (Vissa kompilatorer ger dig dock möjlighet att använda processorns inneboende för att utföra beräkningen.)
  • @ I silico menade jag inte ’ att den beräknar den slutliga värde, jag menade att kompilatorerna kommer att optimera bort funktionssamtalet, så du har bara råekvationen.
  • @josefx: Visst att det ’ är en god anledning. En enda * är en lexikal token, oavsett om den ’ används för inriktning eller multiplikation. En ** som betyder exponentiering skulle vara antingen en eller två lexikala tokens, och du vill verkligen inte att ’ vill att din lexer måste träffa symbolen tabell för att tokenize.

Svar

Faktum är att aritmetiska operatorer bara är genvägar till funktioner. (Nästan) Allt du gör med dem kan göras med en funktion. Exempel:

c = a + b; // equals c.set(a.add(b)); // or as free functions set(c, add(a,b)); 

Det är bara mer detaljerat, så jag ser inget fel med att använda funktioner för att utföra ”power of”.

Svar

Addition / subtraktion / negation och multiplikation / division är grundläggande matematiska operatorer. Om du skulle göra makten till en operatör, var skulle du stoppa? operatör? N-root-operatör? Logaritmoperatör?

Jag kan inte tala för deras skapare, men jag kan säga att jag tycker att det skulle bli svårt och inte ortogonalt att ha sådana operatörer på språket. antalet icke alfanumeriska / vita blanksteg som finns kvar på tangentbordet är ganska begränsat. Som det är är det konstigt att det finns en moduloperator i C ++.

Kommentarer

  • +1 – Jag ser inte ’ t varför det är konstigt att ha mod som operatör. div id = ”749f89ae7f”>

är vanligtvis en enda instruktion. Det ’ är en primativ operation på heltal. Det ’ används mest överallt inom datavetenskap.(Implementering av saker som begränsade buffertar utanmodskulle stinka)

  • @Billy ONeal: Konstigt på grund av inkonsekvensen mellan att kunna använda med heltalstyper och flytande punkttyper . Helt användbart men jag skulle inte ’ drömma om att ta bort den. Bara udda är allt.
  • Lämna ett svar

    Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *