Waarom is er geen power-operator in Java / C ++?

Hoewel er zon operator – ** in Python is, vroeg ik me af waarom Java en C ++ niet hebben een ook.

Het is gemakkelijk om er een te maken voor klassen die je definieert in C ++ met overbelasting van de operator (en ik geloof dat zoiets ook mogelijk is in Java), maar als we het hebben over primitieve typen zoals int, double en enzovoort, je zult een bibliotheekfunctie moeten gebruiken zoals Math.power (en meestal moet je beide casten om te verdubbelen).

Dus – waarom zou je zon operator niet definiëren? voor primitieve typen?

Opmerkingen

  • In C ++ kunnen we onze eigen operatoren niet creëren. Je kunt alleen de bestaande operators overbelasten.
  • @Mahesh, dus ik kan mijn eigen Number class creëren en ^ operator overbelasten om een macht te zijn. Dat is echt niet zo.
  • @RanZilber: Het doet er wel toe omdat de prioriteit van de ^ -operator niet overeenkomt met de prioriteit van machtsverheffen. Beschouw de uitdrukking a + b ^ c. In de wiskunde wordt de machtsverheffing eerst uitgevoerd (b ^ c), en vervolgens wordt de resulterende macht toegevoegd aan a. In C ++ wordt de toevoeging eerst uitgevoerd (a + b) en vervolgens wordt de operator ^ uitgevoerd met c. Dus zelfs als je de ^ operator zou implementeren om machtsverheffen te betekenen, zal de prioriteit iedereen verbazen.
  • @RamZilber – ^ is een XOR in C ++. Het wordt aangeraden dat een overbelaste operator niet anders doet dan een primitief gegevenstype ermee doet.
  • @RanZilber: Omdat het ‘ helemaal niet intuïtief te gebruiken is elk van die operators die u noemt om machtsverheffen te betekenen. Ik zou ernstig twijfelen aan de competentie van elke C ++ programmeur die de ++ operator of de ! operator overbelast et. al. om exponentatie te betekenen. Maar je kunt het sowieso niet ‘ gebruiken, omdat de operatoren waarover je spreekt maar één argument accepteren; machtsverheffen vereist twee argumenten.

Antwoord

Over het algemeen gesproken zijn de primitieve operatoren in C (en bij uitbreiding C ++) zijn ontworpen om geïmplementeerd te kunnen worden door eenvoudige hardware in ongeveer een enkele instructie. Zoiets als machtsverheffen vereist vaak softwareondersteuning; dus het is er standaard niet.

Het wordt ook geleverd door de standaardbibliotheek van de taal in de vorm van std::pow.

Ten slotte zou het niet veel zin hebben om dit te doen voor datatypes met gehele getallen, omdat de meeste zelfs kleine waarden voor machtsverheffen het bereik uitblazen dat vereist is voor int, dat wil zeggen tot 65.535. Natuurlijk zou je dit kunnen doen voor doubles en floats, maar niet ints, maar waarom zou de taal inconsistent maken voor een zelden gebruikte functie?

Opmerkingen

  • Hoewel ik het met de meeste hiervan eens ben, is het feit dat de modulus operator kan niet worden gebruikt op typen met drijvende komma is inconsistent voor primitieve gegevenstypen, maar ook dat zou waarschijnlijk geen enkele instructie zijn op hardware waarvan ik vermoed dat die nu op enige manier gangbaar is.
  • @Sion: tenminste op x86, modulus is een enkele instructie. (DIV doet zowel deling als modulus) Je ‘ hebt me echter op het punt van consistentie gebracht.
  • @Billy ONeal: Floating point modu lus in een enkele instructie? Ik heb ‘ de laatste tijd niet rondgeploegd tijdens de montage om het zelf te weten. Als dat ‘ het geval is, dan zou de modulus-operator toegepast moeten worden op drijvende-kommatypen.
  • @DonalFellows: FORTRAN had de machtsverheffenoperator lang voordat deze had alles wat lijkt op bignum-ondersteuning.
  • @DonalFellows: Een power-operator is niet ‘ t net zo handig met gehele getallen als met drijvers, maar voor kleine machten (vooral kwadraten) hebben zeker zijn toepassingen. Persoonlijk vind ik de aanpak om operators uit letters te maken (zoals Pascal doet met div of FORTRAN met .EQ.); afhankelijk van de witruimteregels van de taal, kan het mogelijk zijn om een willekeurig aantal operators te hebben zonder dat het gereserveerde woorden moeten zijn.

Answer

Deze vraag is te beantwoorden voor C ++: Stroustrup,” Design and Evolution of C ++ “bespreekt dit in sectie 11.6.1, pp. 247-250.

Er waren algemene bezwaren tegen het toevoegen van een nieuwe operator. Het zou bijdragen aan de al te ingewikkelde prioriteitstabel. De leden van de werkgroep dachten dat het maar weinig gemak zou bieden boven het hebben van een functie, en ze wilden soms hun eigen functies kunnen vervangen.

Er was geen goede kandidaat voor een operator.^ is exclusief – of, en ^^ veroorzaakte verwarring vanwege de relatie tussen & en | en && en ||. ! was ongeschikt omdat er een natuurlijke neiging zou zijn om != te schrijven voor machtsverheffen van een bestaande waarde, en die was al in gebruik. De best beschikbare was wellicht *^, wat blijkbaar niemand echt leuk vond.

Stroustrup overwoog ** opnieuw, maar heeft al een betekenis in C: a**p is a keer wat p verwijst naar, en char ** c; declareert c als een pointer naar char. Introductie van ** als een token wat betekent “declaratie van een pointer om aan te wijzen”, “maal wat het volgende ding verwijst” (als het “een pointer is) of” exponentiation “(indien gevolgd door een cijfer) veroorzaakte voorrangsproblemen. a/b**p zou moeten parseren als a/(b**p) als p een getal was, maar (a/b) * *p als p een pointer was, dan zou dit moeten worden opgelost in de parser.

Met andere woorden, het zou mogelijk zijn geweest, maar het zou de voorrangstabel en de parser, en beide zijn al te ingewikkeld.

Ik ken het verhaal over Java niet; ik zou alleen maar kunnen speculeren. Wat betreft C, waar het begon, worden alle C-operators gemakkelijk vertaald in assembly-code, deels om de compiler te vereenvoudigen en deels om te voorkomen dat tijdrovende functionaliteit in eenvoudige operators wordt verborgen (het feit dat operator+() en anderen konden grote complexiteit verbergen en prestatiehits was een van de eerste klachten over C ++).

Reacties

  • Mooi antwoord. Ik denk dat Java in dit opzicht heeft geprobeerd C te vereenvoudigen, dus niemand wilde een nieuwe operator toevoegen. Dat ‘ is jammer dat niemand het mij heeft gevraagd, ik had zeker graag *^ gehad. : D
  • C is gebouwd om tekst op te maken. Fortran is gebouwd om wiskunde te doen en had 20 jaar eerder complexe, krachtige en matrixberekeningen.
  • @Martin Beckett: Kun je bewijs vinden dat C is gebouwd voor tekstopmaak? Het lijkt me daarvoor een erg onhandige taal, en wat ik ‘ heb gelezen over de oorsprong van C, zegt dat het voornamelijk is ontworpen voor systeemprogrammering voor Unix.
  • @DavidThornley – Het is ontworpen om Unix in te schrijven, maar al het vroege Unix-gebruik lijkt tekstopmaak te zijn geweest, en daarom ‘ heeft het een uitgebreide string en i / o bibliotheek.
  • +1: de bestaande betekenis voor a**p is de moordenaar. (De hacks om dat probleem te omzeilen … Brr!)

Antwoord

Ik vermoed het is omdat elke operator die je invoert de complexiteit van de taal vergroot. De toetredingsdrempel is daarom erg hoog. Ik merk dat ik machtsverheffen heel, heel zelden gebruik – en ik gebruik graag een methodeaanroep om te doen dus.

Reacties

  • Elke feature begint met -100 punten.
  • Ik ‘ d gebruik x**2 en x**3 niet zo zelden . En een magische pow-implementatie die de compiler kent en optimaliseert voor de eenvoudige gevallen zou leuk zijn.
  • @CodeInChaos: x * x en x * x * x zijn ‘ geen slechte substituten voor het vierkant en de kubus.
  • @David je kunt ‘ t gewoon x*x schrijven als x een uitdrukking is. In het beste geval wordt de code onpraktisch, en in het ergste geval langzamer of zelfs verkeerd. Dus u ‘ moet uw eigen Square- en Cube-functies definiëren. En zelfs dan zou de code lelijker zijn dan ** als energiebeheerder te gebruiken.
  • @David Ik moet haakjes plaatsen ja, maar ‘ niet herhalen de uitdrukking meerdere keren en bloats de broncode. Wat de leesbaarheid aanzienlijk vermindert. En algemene eliminatie van subexpressies is alleen mogelijk als de compiler kan garanderen dat de expressie vrij is van bijwerkingen. En tenminste .net jitter is niet ‘ t te slim in dat opzicht.

Antwoord

De ontwerpers van de Java-taal en kernbibliotheek hebben besloten de meeste wiskundige bewerkingen te degraderen naar de klasse Math . Zie Math.pow () .

Waarom? Flexibiliteit om voorrang te geven aan prestaties boven bit-voor-bit-precisie.Het zou in strijd zijn met de rest van de taalspecificatie om te zeggen dat het gedrag van ingebouwde wiskundige operators kan variëren van platform tot platform, terwijl de Math-klasse specifiek aangeeft dat het gedrag mogelijk precisie opoffert voor prestaties, dus pas op voor de koper:

In tegenstelling tot sommige numerieke methoden van class StrictMath , alle implementaties van de equivalente functies van class Wiskunde is niet gedefinieerd om dezelfde resultaten bit-voor-bit te retourneren. Deze versoepeling maakt beter presterende implementaties mogelijk waar strikte reproduceerbaarheid niet vereist is.

Antwoord

Exponentiatie maakte vanaf het begin deel uit van Fortran omdat het rechtstreeks gericht was op wetenschappelijke programmering. Ingenieurs en natuurkundigen gebruiken het vaak in simulaties, omdat machtswetten in de natuurkunde veel voorkomen.

Python is ook sterk aanwezig in wetenschappelijk computergebruik (bijvoorbeeld NumPy en SciPy). Dat, samen met zijn machtsverheffenoperator, suggereert dat het ook gericht was op wetenschappelijk programmeren.

C, Java en C # hebben wortels in systeemprogrammering. Misschien “is dat een invloed die machtsverheffen buiten de groep van ondersteunde operatoren hield.

Gewoon een theorie.

Antwoord

C-gedefinieerde operatoren alleen voor gewone rekenkundige bewerkingen die toegankelijk zijn met de ALU. Het belangrijkste doel was het creëren van een voor mensen leesbare interface naar Assembly-code.

C ++ veranderde geen enkel operatorgedrag omdat het alles wilde de codebasis geschreven in C om compliant te zijn.

Java deed hetzelfde omdat het “bestaande C ++ programmeurs niet wilde intimideren.

Opmerkingen

  • Toen C werd gemaakt, ontbraken vermenigvuldiging en deling niet zelden in hardware en moesten ze in software worden geïmplementeerd. Toch heeft C operators voor vermenigvuldigen en delen.
  • @siride: Voor zover ik weet, had de PDP-7, de eerste computer waarop Unix draaide, hardware vermenigvuldiging en verdeling via zijn EAE. Zie: bitsavers.org/pdf/dec/pdp7/F-75_PDP-7userHbk_Jun65.pdf

Antwoord

Nou, omdat elke operator die zinvol zou zijn voor een macht al in gebruik is. ^ is XOR en ** definieert een pointer naar een pointer. Dus in plaats daarvan hebben ze gewoon een functie die hetzelfde doet. (like pow ())

Reacties

  • @RTS – Zoekt een taalontwikkelaar echt meer naar zin dan naar efficiëntie?
  • Een goede ontwikkelaar van een programmeertaal kijkt naar beide. Ik kan ‘ niets zeggen over Java. Maar in c ++ wordt de pow () -functie berekend tijdens het compileren. En is net zo efficiënt als de reguliere operatoren.
  • @RTS: De pow() -functie voert zijn berekening uit tijdens runtime, tenzij je een compiler hebt die constant kan vouwen voor pow(), wat ik ten zeerste betwijfel. (Sommige compilers geven je echter de mogelijkheid om processorintrinsiek te gebruiken om de berekening uit te voeren.)
  • @In silico Ik bedoelde niet ‘ dat het de uiteindelijke waarde, ik bedoelde dat de compilers de functieaanroep zullen optimaliseren, dus je hebt alleen de ruwe vergelijking.
  • @josefx: Tuurlijk ‘ is een goede reden. Een enkele * is een lexicaal token, of het nu ‘ s wordt gebruikt voor indirecte of vermenigvuldiging. Een **, wat betekent dat machtsverheffen één of twee lexicale tokens zijn, en je wilt echt niet dat ‘ je lexer het symbool moet raken tabel om te tokeniseren.

Antwoord

Feit is dat rekenkundige operatoren slechts snelkoppelingen van functies zijn. (Bijna) Alles wat je ermee doet, kan met een functie worden gedaan. Voorbeeld:

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

Het is gewoon meer uitgebreid, dus ik zie niets mis met het gebruik van functies om “power of” uit te voeren.

Answer

Optellen / aftrekken / negeren en vermenigvuldigen / delen zijn elementaire wiskundige operatoren. Als je van macht een operator zou maken, waar zou je dan stoppen? operator? N-root operator? Logaritme-operator?

Ik kan “niet spreken voor hun makers, maar ik kan zeggen dat het” onpraktisch en niet orthogonaal zou worden om dergelijke operatoren in de taal te hebben. het aantal niet-alfanumerieke / witruimte-tekens op het toetsenbord is vrij beperkt. Zoals het nu is, is het vreemd dat er een modulus-operator in C ++ zit.

Opmerkingen

  • +1 – Ik begrijp niet ‘ waarom mod als operator vreemd is. Het ‘ is meestal een enkele instructie. Het ‘ is een primatieve bewerking op gehele getallen. Het ‘ wordt het meest overal in de informatica gebruikt.(Dingen implementeren zoals bounded buffers zonder mod zou stinken)
  • @Billy ONeal: Vreemd vanwege de inconsistentie tussen het kunnen gebruiken met integer-typen en floating-point-typen . Absoluut nuttig en ik zou er niet ‘ niet van dromen om het te verwijderen. Gewoon eigenzinnig is alles.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *