Pourquoi il ny a pas dopérateur de puissance en Java / C ++?

Bien quil existe un tel opérateur – ** en Python, je me demandais pourquoi Java et C ++ nont pas un aussi.

Il est facile den créer un pour les classes que vous définissez en C ++ avec surcharge dopérateurs (et je pense que cela est également possible en Java), mais quand on parle de types primitifs tels que int, double et ainsi de suite, vous « devrez utiliser une fonction de bibliothèque comme Math.power (et vous devrez généralement convertir les deux en double).

Alors – pourquoi ne pas définir un tel opérateur pour les types primitifs?

Commentaires

  • En C ++, nous ne pouvons pas créer nos propres opérateurs. Vous ne pouvez surcharger que les opérateurs existants.
  • @Mahesh, donc je peux créer ma propre classe Number et surcharger lopérateur ^ pour être une puissance. Cela ne marche vraiment pas.
  • @RanZilber: Cela importe parce que la priorité de lopérateur ^ ne correspond pas à la priorité de lexponentiation. Considérez lexpression a + b ^ c. En mathématiques, lexponentiation est dabord effectuée (b ^ c), puis la puissance résultante est ajoutée à a. En C ++, lajout est effectué en premier (a + b) puis lopérateur ^ est effectué avec c. Ainsi, même si vous avez implémenté lopérateur ^ pour signifier lexponentiation, la priorité surprendra tout le monde.
  • @RamZilber – ^ est un XOR en C ++. Il est conseillé que lopérateur surchargé ne fasse pas différent de ce quun type de données primitif fait en lutilisant.
  • @RanZilber: Parce quil ‘ nest pas du tout intuitif à utiliser lun de ces opérateurs que vous mentionnez pour signifier lexponentiation. Je remettrais sérieusement en question la compétence de tout programmeur C ++ qui surcharge lopérateur ++ ou lopérateur ! et. Al. pour signifier lexponentation. Mais vous pouvez ‘ t de toute façon, car les opérateurs dont vous parlez nacceptent quun seul argument; lexponentiation nécessite deux arguments.

Réponse

Dune manière générale, les opérateurs primitifs en C (et par extension C ++) sont conçus pour être implémentables par du matériel simple en une seule instruction. Quelque chose comme lexponentiation nécessite souvent un support logiciel; donc ce nest pas là par défaut.

De plus, il est fourni par la bibliothèque standard de la langue sous la forme std::pow.

Enfin, faire cela pour les types de données entiers naurait pas beaucoup de sens, car la plupart des petites valeurs dexponentiation dépassent la plage requise pour int, cest-à-dire jusquà 65 535. Bien sûr, vous pouvez le faire pour les doubles et les flottants, mais pas ints, mais pourquoi rendre le langage incohérent pour une fonctionnalité rarement utilisée?

Commentaires

  • Bien que je sois daccord avec la plupart de cela, le fait que le module Lopérateur ne peut pas être utilisé sur les types à virgule flottante est incohérent pour les types de données primitifs, mais cela ne serait probablement pas une seule instruction sur un matériel que jimagine est de toute façon répandu maintenant.
  • @Sion: Au moins sur x86, le module est une seule instruction. (DIV fait à la fois la division et le module) Vous ‘ mavez par contre mis sur le point de cohérence.
  • @Billy ONeal: modu virgule flottante lus en une seule instruction? Je nai pas ‘ été bousillé en assemblée ces derniers temps pour le savoir par moi-même. Si cela ‘ est le cas, alors lopérateur de module devrait être rendu applicable aux types à virgule flottante.
  • @DonalFellows: FORTRAN avait lopérateur dexponentiation bien avant tout ce qui ressemble au support bignum.
  • @DonalFellows: Un opérateur de puissance nest ‘ t aussi utile avec les entiers quavec les flottants, mais pour les petites puissances (en particulier la quadrature) ont certainement ses utilisations. Personnellement jaime lapproche de faire des opérateurs en lettres (comme Pascal le fait avec div ou FORTRAN avec .EQ.); selon les règles despaces de langue, il peut être possible davoir un nombre arbitraire dopérateurs sans exiger quils soient des mots réservés.

Réponse

Cette question peut répondre pour C ++: Stroustrup, » Design and Evolution of C ++ « traite de cela dans la section 11.6.1, pp. 247-250.

Il y avait des objections générales à lajout dun nouvel opérateur. Cela ajouterait à la table de priorité déjà trop compliquée. Les membres du groupe de travail pensaient que cela ne leur apporterait quune commodité mineure sur le fait davoir une fonction, et ils voulaient parfois pouvoir remplacer leurs propres fonctions.

Il ny avait pas de bon candidat pour un opérateur.^ est exclusif-or, et ^^ a suscité la confusion en raison de la relation entre & et | et && et ||. ! ne convenait pas car il y aurait la tendance naturelle décrire != pour lexponentiation dune valeur existante, et cela a déjà été pris. Le meilleur disponible a peut-être été *^, ce que personne na apparemment vraiment aimé.

Stroustrup a de nouveau considéré **, mais il a déjà une signification en C: a**p est a fois ce que p pointe, et char ** c; déclare c comme un pointeur vers un pointeur vers char. Présentation de ** comme un jeton signifiant « déclaration dun pointeur vers un pointeur vers », « multiplié par ce que la prochaine chose pointe vers » (sil « sagit dun pointeur) ou » exponentiation « (si suivi) par un nombre) causait des problèmes de priorité. a/b**p devrait analyser comme a/(b**p) si p était un nombre, mais (a/b) * *p si p était un pointeur, cela devrait donc être résolu dans lanalyseur.

En dautres termes, cela aurait été possible, mais cela aurait compliqué la table de précédence et le parser, et les deux sont déjà trop compliqués.

Je ne connais pas lhistoire de Java; tout ce que je pourrais faire serait de spéculer. Quant au C, là où il a commencé, tous les opérateurs C sont facilement traduits en code dassemblage, en partie pour simplifier le compilateur et en partie pour éviter de cacher des fonctionnalités chronophages dans des opérateurs simples (le fait que operator+() et dautres pourraient cacher une grande complexité et les performances ont été lune des premières plaintes à propos du C ++.

Commentaires

  • Bonne réponse. Je suppose que Java a essayé dêtre simplifié C à cet égard, donc personne ne voulait ajouter un nouvel opérateur. Que ‘ soit dommage que personne ne me le demande, jaurais sûrement aimé *^. : D
  • C a été conçu pour mettre en forme du texte. Fortran a été conçu pour faire des mathématiques et avait des mathématiques complexes, puissantes et matricielles 20 ans plus tôt.
  • @Martin Beckett: Pouvez-vous trouver des preuves que C a été conçu pour le formatage de texte? Cela me semble un langage très maladroit pour cela, et ce que jai ‘ lu sur lorigine de C dit quil a été conçu pour la programmation système sous Unix principalement.
  • @DavidThornley – Il a été conçu pour écrire sous Unix, mais toutes les premières utilisations dUnix semblent avoir été le formatage de texte, et pour cela ‘ il a une chaîne étendue et i / o bibliothèque.
  • +1: La signification existante de a**p est le tueur. (Les hacks pour contourner ce problème… Brr!)

Réponse

Je suspecte cest parce que chaque opérateur que vous introduisez augmente la complexité du langage. La barrière à lentrée est donc très élevée. Je me retrouve à utiliser très, très rarement lexponentiation – et je suis plus quheureux dutiliser un appel de méthode pour faire oui.

Commentaires

  • Chaque fonctionnalité commence par -100 points.
  • Jutilise ‘ x**2 et x**3 pas si rarement . Et une implémentation magique que le compilateur connaît et optimise pour les cas simples serait bien.
  • @CodeInChaos: Cependant x * x et x * x * x aren ‘ t de mauvais substituts pour le carré et le cube.
  • @David vous pouvez ‘ t écrivez simplement x*x si x est une expression. Dans le meilleur des cas, le code devient peu maniable, et dans le pire des cas plus lent, voire faux. Ainsi, vous ‘ devez définir vos propres fonctions Square et Cube. Et même dans ce cas, le code serait plus moche que dutiliser ** comme opérateur dalimentation.
  • @David Je dois mettre des parenthèses oui, mais ‘ t besoin de répéter lexpression plusieurs fois et gonfle le code source. Ce qui réduit beaucoup la lisibilité. Et lélimination des sous-expressions courantes nest possible que si le compilateur peut garantir que lexpression est exempte deffets secondaires. Et au moins .net jitter nest pas ‘ trop intelligent à cet égard.

Réponse

Les concepteurs du langage Java et de la bibliothèque principale ont décidé de reléguer la plupart des opérations mathématiques à la classe Math . Voir Math.pow () .

Pourquoi? Flexibilité pour donner la priorité aux performances par rapport à la précision bit à bit.Cela irait à lencontre du reste de la spécification du langage de dire que le comportement des opérateurs mathématiques intégrés pourrait varier dune plate-forme à lautre, alors que la classe Math déclare spécifiquement que le comportement sacrifie potentiellement la précision pour les performances, donc lacheteur se méfie:

Contrairement à certaines des méthodes numériques de la classe StrictMath , toutes les implémentations des fonctions équivalentes de la classe Les mathématiques ne sont pas définies pour renvoyer les mêmes résultats bit à bit. Cette relaxation permet des implémentations plus performantes où une reproductibilité stricte nest pas requise.

Réponse

Lexponentiation faisait partie de Fortran depuis le début car elle visait carrément la programmation scientifique. Les ingénieurs et les physiciens lutilisent souvent dans les simulations, car les relations de loi de puissance sont courantes en physique.

Python a également une forte présence dans le calcul scientifique (par exemple NumPy et SciPy). Cela, avec son opérateur dexponentiation, suggère quil était également destiné à la programmation scientifique.

C, Java et C # ont des racines dans la programmation système. Cest peut-être une influence qui a empêché lexponentiation du groupe dopérateurs pris en charge.

Juste une théorie.

Réponse

Opérateurs définis en C uniquement pour les opérations arithmétiques courantes accessibles avec lALU. Son objectif principal était de créer une interface lisible par lhomme vers le code dassemblage.

C ++ na changé aucun comportement dopérateur car il voulait tout la base de code écrite en C pour être conforme.

Java a fait de même car il ne voulait pas intimider les programmeurs C ++ existants.

Commentaires

  • Lors de la création de C, la multiplication et la division ne manquaient pas rarement de matériel et devaient être implémentées dans le logiciel. Pourtant, C a des opérateurs de multiplication et de division.
  • @siride: À ma connaissance, le PDP-7, le premier ordinateur à exécuter Unix, avait une multiplication et une division matérielles via son EAE. Veuillez consulter: bitsavers.org/pdf/dec/pdp7/F-75_PDP-7userHbk_Jun65.pdf

Réponse

Eh bien, parce que chaque opérateur qui aurait du sens pour une puissance est déjà utilisé. ^ est XOR et ** définit un pointeur vers un pointeur. Au lieu de cela, ils ont juste une fonction qui fait la même chose. (comme pow ())

Commentaires

  • @RTS – Un développeur de langage recherche-t-il vraiment plus de sens que defficacité?
  • Un bon développeur dun langage de programmation regarde les deux. Je ne peux ‘ rien dire sur java. Mais en C ++, la fonction pow () est calculée au moment de la compilation. Et est tout aussi efficace que les opérateurs réguliers.
  • @RTS: La fonction pow() effectue son calcul à lexécution, à moins que vous nayez un compilateur capable de faire un repli constant pour pow(), dont je doute fortement. (Cependant, certains compilateurs vous offrent la possibilité dutiliser les éléments intrinsèques du processeur pour effectuer le calcul.)
  • @In silico, je nai ‘ que cela signifie quil calcule le résultat final value, je voulais dire que les compilateurs optimiseront lappel de fonction, donc vous navez que léquation brute.
  • @josefx: Bien sûr, ‘ est une bonne raison. Un seul * est un jeton lexical, quil soit ‘ utilisé pour lindirection ou la multiplication. Une ** signifiant exponentiation serait soit un ou deux jetons lexicaux, et vous ne ‘ ne voulez pas que votre lexeur frappe le symbole table à tokenize.

Réponse

Le fait est que les opérateurs arithmétiques ne sont que des raccourcis de fonctions. (Presque) Tout ce que vous en faites peut être fait avec une fonction. Exemple:

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

Cest juste plus verbeux, donc je ne vois rien de mal à utiliser des fonctions pour exécuter « power of ».

Réponse

Addition / soustraction / négation et multiplication / division sont des opérateurs mathématiques de base. Si vous deviez faire de la puissance un opérateur, où vous arrêteriez-vous? Racine carrée opérateur? Opérateur N-racine? Opérateur logarithme?

Je ne peux pas parler au nom de leurs créateurs, mais je peux dire que je pense que cela deviendrait compliqué et pas orthogonal davoir de tels opérateurs dans le langage. le nombre de caractères non alphanumériques / espace blanc restant sur le clavier est plutôt limité. En létat, il est étrange quil existe un opérateur de module en C ++.

Commentaires

  • +1 – Je ne ‘ pas voir pourquoi avoir mod comme opérateur est étrange. Cela ‘ est généralement une seule instruction. Elle ‘ est une opération primitive sur les entiers. Elle ‘ est utilisé le plus partout en informatique.(Mettre en œuvre des choses comme des tampons bornés sans mod serait puant)
  • @Billy ONeal: étrange en raison de lincohérence entre la possibilité dutiliser des types entiers et des types à virgule flottante . Absolument utile et je ne rêverais ‘ de le supprimer. Tout simplement excentrique.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *