OVH Cloud OVH Cloud

Surcharge et priorité

39 réponses
Avatar
Etienne Rousee
Bonsoir,

J'écris une bibliothèque de polynômes et j'ai
quelques problèmes avec l'opérateur exposant (^).
J'ai écrit toutes les surcharges nécessaires et
ceci par, exemple, compile:
Polynome P = (X^3) - 6 * (X^2) + 9 * X - 4;
Par contre, ceci ne compile pas:
Polynome P = X^3 - 6 * X^2 + 9 * X - 4;
Par ailleurs X^2 - 1 compile et donne X.
Je n'ai donc pas la bonne priorité.

Y a-t-il moyen d'arranger ça ?

--

Etienne

10 réponses

1 2 3 4
Avatar
James Kanze
Cyrille wrote:

Il n'y aurait pas un autre opérateur caché que je pourrais
détourner du droit chemin ?



Il te faudrait, si j'ai bien compris, un opérateur binaire plus
prioritaire que +, -, *, /, mais moins que ().
D'après la table en bas de
http://www.cplusplus.com/doc/tutorial/operators.html
il n'y a que .* et ->* qui fassent l'affaire, mais ils font
partie des rares qui ne peuvent pas être surchargés. :)


D'où as-tu ça ? ->* est un opérateur binaire comme n'importe
quel autre opérateur binaire, et on peut très bien le
surcharger.

Si c'est une bonne idée, c'est une autre question.

Ceci dit, [] pourrait faire l'affaire...


En général, on préfère que l'opérateur surchargé ait une
sémantique apparentée à celle de l'opérateur de base. Et vice
versa. L'opérateur de puissance, en C++, ne s'écrit ni ^ ni ->*
ni []. Le surcharge d'un de ces opérateurs pour signifier la
puissance n'est donc pas une bonne idée ; il fait que ta classe
a une syntaxe différente de celle à laquelle on s'attendra.

En C++, la puissance sur des doubles et al. s'écrit
« pow(x,y) ». Il me semble donc que la seule solution logique
pour une classe utilisateur qui définit la puissance, c'est
qu'il utilise l'« opérateur » pow(...). Qui peut être surchargé,
et qui a en plus la bonne précédence.

Je ne suis sûrement pas le premier à écrire
une telle bibliothèque. Comment font les autres ?



Ils se modèlent sur les types de bases, et surchargent pow ?

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34


Avatar
James Kanze
Marc Boyer wrote:

Il est quand même plus courant en maths d'écrire pgcd(a,b)
et ppcm(a,b). C'est d'ailleurs la notation utilisée en lycée,
probablement parce que ^ est la puissance sur les
calculatrices.



Et puis aussi parce que ^, c'est l'exposant en LaTeX, et que
je pense qu'une vaste majorité des mathématiciens actuels
écrivent leurs papiers en LaTeX.


De l'autre part, ** est l'exposant en Fortran, et la vaste
majorité des mathémataticiens, au moins il y a un certain temps,
ne connaissaient que le Fortran.

La question a été discutée en C++. Il était clair que ^ ne fait
pas l'affaire, d'une part à cause de la précédence, et de
l'autre parce qu'on n'accepte pas qu'un opérateur ait une
signification si radicalement différente pour les entiers et
pour les flottants. On a considéré **, comme en Fortran ; le
problème, c'est que a ** b est déjà une expression légale. À la
fin, on a trouvé *^ comme opérateur. Mais on a finalement décidé
que les avantages par rapport à pow(a, b) n'en valaient pas la
peine.

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34


Avatar
kanze
Etienne Rousee wrote:

J'écris une bibliothèque de polynômes et j'ai
quelques problèmes avec l'opérateur exposant (^).


J'en reviens toujours -- cette fois-ci, je m'adresse à la
source:-).

D'où tiens-tu l'idée qu'en C++, ^ est l'opérateur exposant (ou
de puissance) ? Si j'écris du texte en ASCII, j'utilise parfois
^ pour indiquer que ce qui suit est en superscript : surélevé et
plus petit. Parce que c'est la signification de ^ en LaTeX ;
j'utilise aussi parfois _ pour indiquer un subscript. Mais c'est
une convention de formattage de texte, et non un opérateur de
C++.

J'ai écrit toutes les surcharges nécessaires et
ceci par, exemple, compile:
Polynome P = (X^3) - 6 * (X^2) + 9 * X - 4;


Si X est un entier, ça doit compiler. C'est normal.

Si X est un type qui « ressemble » à un entier, il est aussi
normal de surcharger l'opérateur ^ pour qu'il se comporte comme
sur les entiers, c-à-d qu'il effectue un ou exclusif.

Si ce que tu veux, c'est X puissance 3, etc., en C++ (comme en

Polynome P = pow(X,3) - 6 * pow(X,2) + 9 * X - 4 ;

C'est du C++ ; en Fortran, je m'attendrais à quelque chose
comme :
P = X**3 - 6*X**2 + 9*X - 4
Mais ici, on ne considère que le C++.

Si je veux que ça se formatte comme une expression mathématique
habituelle, j'écrirais :

P = X^3 - 6X^2 + 9X - 4

et je passerais mon texte ASCII à LaTeX, pour avoir quelque
chose de joli. Mais il s'agit là d'une spécification de
présentation, non d'un opérateur (et évidemment, en C++, cette
notation pose d'autres problèmes).

En somme, chaque langage a ces conventions ; quand on travaille
dans un langage X, il vaut mieux suivre les conventions du
langage X, et non en inventer des nouvelles.

Par contre, ceci ne compile pas:
Polynome P = X^3 - 6 * X^2 + 9 * X - 4;
Par ailleurs X^2 - 1 compile et donne X.
Je n'ai donc pas la bonne priorité.

Y a-t-il moyen d'arranger ça ?


Écrire du C++, et non du LaTeX. Si le fait qu'il faut écrire
9*X, et non simplement 9X, ne te gène pas, où est le problème
avec pow(X,3), plutôt que X^3 ?

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Etienne Rousee
"kanze" a écrit ...
Etienne Rousee wrote:

J'écris une bibliothèque de polynômes et j'ai
quelques problèmes avec l'opérateur exposant (^).


J'en reviens toujours -- cette fois-ci, je m'adresse à la
source:-).


:-)

D'où tiens-tu l'idée qu'en C++, ^ est l'opérateur exposant (ou
de puissance) ?


Je sais bien que non.

Si j'écris du texte en ASCII, j'utilise parfois
^ pour indiquer que ce qui suit est en superscript : surélevé et
plus petit. Parce que c'est la signification de ^ en LaTeX ;
j'utilise aussi parfois _ pour indiquer un subscript. Mais c'est
une convention de formattage de texte, et non un opérateur de
C++.


Oui.
Sur fr.sci.math, on utilise ^ pour l'exposant.
Sur ma calculatrice aussi.
Ce qui explique que j'en ai l'habitude.

J'ai écrit toutes les surcharges nécessaires et
ceci par, exemple, compile:
Polynome P = (X^3) - 6 * (X^2) + 9 * X - 4;


Si X est un entier, ça doit compiler. C'est normal.


Non, X est un polynôme (c'est 1.0 X ^ 0),
classe que j'ai implémentée avec entre autres
un deque <Monome>, un Monome contenant
und coefficient (double) et un degré (int).

Si X est un type qui « ressemble » à un entier, il est aussi
normal de surcharger l'opérateur ^ pour qu'il se comporte comme
sur les entiers, c-à-d qu'il effectue un ou exclusif.


Ce n'est pas le cas, et je n'ai pas besoin de ou exclusif
dans ce contexte.

Si ce que tu veux, c'est X puissance 3, etc., en C++ (comme en

Polynome P = pow(X,3) - 6 * pow(X,2) + 9 * X - 4 ;


Ben oui, mais je trouve que ce n'est pas très beau.
Je sais, c'est subjectif.

C'est du C++ ; en Fortran, je m'attendrais à quelque chose
comme :
P = X**3 - 6*X**2 + 9*X - 4


Je trouve que c'est déjà un peu plus joli.

Mais ici, on ne considère que le C++.

Si je veux que ça se formatte comme une expression mathématique
habituelle, j'écrirais :

P = X^3 - 6X^2 + 9X - 4


C'est ce que j'aurai voulu.
Pour le moment, j'ai:
P = (X^3) - 6.0 * (X^2) + 9.0 * X - 4.0
qui fonctionne, bien sûr.

et je passerais mon texte ASCII à LaTeX, pour avoir quelque
chose de joli. Mais il s'agit là d'une spécification de
présentation, non d'un opérateur (et évidemment, en C++, cette
notation pose d'autres problèmes).


Ok.

En somme, chaque langage a ces conventions ; quand on travaille
dans un langage X, il vaut mieux suivre les conventions du
langage X, et non en inventer des nouvelles.


Ok.

Par contre, ceci ne compile pas:
Polynome P = X^3 - 6 * X^2 + 9 * X - 4;
Par ailleurs X^2 - 1 compile et donne X.
Je n'ai donc pas la bonne priorité.

Y a-t-il moyen d'arranger ça ?


Écrire du C++, et non du LaTeX. Si le fait qu'il faut écrire
9*X, et non simplement 9X, ne te gène pas, où est le problème
avec pow(X,3), plutôt que X^3 ?


C'est juste ma notion personnelle de l'esthétique.

Mais je suis d'accord avec toi sur le fond.

--

Etienne


Avatar
Vincent Lascaux
Je ne sais pas ce que font les autres, mais on peut imaginer:
Polynome P = X[2] - 1
Polynome P = X_2 - 1 (avec X_N définit pour les N les plus courants)
Polynome P = X<2>::value - 1 avec des template mais ça devient cryptique.
Polynome P = pow(X, 2) - 1


On peut aussi imaginer ca :

struct pow
{
pow(int exp)
: exp(exp)
{ }
int exp;
};
Polynome operator * (const Polynome& p, const pow& e)
{
return pow(p, e.exp);
}

Ca permet d'écrire X * pow(2)

Ensuite on peut définir
template<int n> pow* getPow() { static pow p(n); return &p; }
const pow* _0 = getPow<0>();
const pow* _1 = getPow<1>();
const pow* _2 = getPow<2>();
const pow* _3 = getPow<3>();
...

Ca permet d'écrire (1 + X) ** _2
Ca me semble toujours assez obfuscé par rapport à pow(1+X, 2) mais c'est
rigolo

--
Vincent

Avatar
Fabien LE LEZ
On Tue, 27 Dec 2005 15:35:08 -0800, "Vincent Lascaux"
:

Ca permet d'écrire (1 + X) ** _2


Et (3 * X ** _2), qui ne fait pas vraiment ce qu'on attend de lui :-)

Avatar
Cyrille
/snip
Ca permet d'écrire (1 + X) ** _2
Ca me semble toujours assez obfuscé par rapport à pow(1+X, 2) mais c'est
rigolo


En fait j'ai trouvé la solution ultime:
Polynome p = "(1 + X)^2 - 4";
Le constructeur de Polynome contenant un parser fait maison, ainsi on a
toute liberté pour donner à n'importe quel signe le sens qu'on désire.

Oui, c'est triché et la validité de la syntaxe n'est pas vérifiée à la
compilation, mais bon...

Avatar
Fabien LE LEZ
On Wed, 28 Dec 2005 01:23:38 +0100, Cyrille :

En fait j'ai trouvé la solution ultime:
Polynome p = "(1 + X)^2 - 4";


Sauf que pour le coup, on est très limité, puisqu'on ne peut employer
qu'une seule variable : X.

Tant qu'à n'utiliser qu'une seule variable, autant construire le
polynôme (x^2 + 2x - 3) comme suit :

Polynome p;
p << 1 << 2 << -3;
Voire
p= 1, 2, -3; /* Il me semble que c'est possible, mais avec un
hack immonde */

ou encore
Polynome p= CreePolynome() << 1 << 2 << -3;

Avatar
Etienne Rousee
"Vincent Lascaux" a écrit ...
Je ne sais pas ce que font les autres, mais on peut imaginer:
Polynome P = X[2] - 1
Polynome P = X_2 - 1 (avec X_N définit pour les N les plus courants)
Polynome P = X<2>::value - 1 avec des template mais ça devient
cryptique.



Pas très beau, tout ça.

Polynome P = pow(X, 2) - 1



Ça non plus, mais bon, si c'est le standard ...

On peut aussi imaginer ca :

struct pow
{
pow(int exp)
: exp(exp)
{ }
int exp;
};
Polynome operator * (const Polynome& p, const pow& e)
{
return pow(p, e.exp);
}

Ca permet d'écrire X * pow(2)

Ensuite on peut définir
template<int n> pow* getPow() { static pow p(n); return &p; }
const pow* _0 = getPow<0>();
const pow* _1 = getPow<1>();
const pow* _2 = getPow<2>();
const pow* _3 = getPow<3>();
...

Ca permet d'écrire (1 + X) ** _2
Ca me semble toujours assez obfuscé par
rapport à pow(1+X, 2) mais c'est rigolo


C'est vrai , c'est rigolo, mais si on pouvait écrire
(1 + X) ** 2 sans le '_' ce serait encore mieux,
et puis le templater pour rendre l'entier n générique
au lieu de prévoir les n les plus "courants" qui
seront forcément incomplets.

--

Etienne


Avatar
kanze
Etienne Rousee wrote:
"kanze" a écrit ...
Etienne Rousee wrote:


[...]
Si j'écris du texte en ASCII, j'utilise parfois ^ pour
indiquer que ce qui suit est en superscript : surélevé et
plus petit. Parce que c'est la signification de ^ en LaTeX ;
j'utilise aussi parfois _ pour indiquer un subscript. Mais
c'est une convention de formattage de texte, et non un
opérateur de C++.


Oui.
Sur fr.sci.math, on utilise ^ pour l'exposant.
Sur ma calculatrice aussi.
Ce qui explique que j'en ai l'habitude.


Tandis que moi, je ne fréquente pas fr.sci.math, et que j'y
pense, je ne sais pas de tête ce qui se trouve sur ma
calculatrice.

En revanche, je connais bien LaTeX. En LaTeX, ^ est l'opérateur
de superscript ; ce n'est l'opérateur de puissance que dans la
mesure que le superscript en question représente une puissance.

[...]
Si ce que tu veux, c'est X puissance 3, etc., en C++ (comme en

Polynome P = pow(X,3) - 6 * pow(X,2) + 9 * X - 4 ;


Ben oui, mais je trouve que ce n'est pas très beau.
Je sais, c'est subjectif.


Je suis un peu d'accord avec toi. N'empèche que le sujet a été
discuté par le comité, et qu'à la fin, les mathématiciens
présentent ont estimé que c'était préférable aux alternatifs.
(Après maintes discussions, la conclusion était que le meilleur
choix pour l'opérateur aurait été *^. C'est une séquence de
caractères qui ne peut pas se présenter dans un programme C++
légal aujourd'hui ; il n'y a donc pas de problèmes de
changements de sémantiques d'un code existant.)

C'est du C++ ; en Fortran, je m'attendrais à quelque chose
comme :
P = X**3 - 6*X**2 + 9*X - 4


Je trouve que c'est déjà un peu plus joli.


Mais le Fortran a peut-être d'autres désavantages:-).

Mais ici, on ne considère que le C++.

Si je veux que ça se formatte comme une expression mathématique
habituelle, j'écrirais :

P = X^3 - 6X^2 + 9X - 4


C'est ce que j'aurai voulu.


Sans opérateur du tout plur la multiplication, je ne vois pas
comment tu peux y arriver.

Le point que je faisais, évidemment, c'est que la notation C++
et la notation mathématique classique vont être différentes. À
commencer par le fait que la notation mathématique exploite
réelement les deux dimensions, et aussi des différences de
police de caractères, et que sais-je d'autre. Mais aussi le fait
que la juxtaposition avec plus ou moins d'espace a une
signification : $6x$ en mathématique doit s'écrire 6*x en C++
(et l'x ne serait pas en italique, comme c'est la convention
dans les expressions mathématique).

Or, du moment qu'on s'est écarté de la notation mathématique
pour suivre des conventions nettement différentes (comme * pour
la multiplication), un peu de plus ou de moins ne me semble pas
si important -- qu'importe si j'écris x^3 ou pow(x, 3), à la
place de $x^3$ (où l'x s'écrit en italique, et le 3 en
superscript) ?

Pour le moment, j'ai:
P = (X^3) - 6.0 * (X^2) + 9.0 * X - 4.0
qui fonctionne, bien sûr.


Mais qui AMHA est trompeur. Je connais le C++ ; je sais donc ce
que signifie l'opérateur ^ en C++. Lui donner une signification
aussi radicalement différente est trompeur, et prête à
confusion.

[...]
C'est juste ma notion personnelle de l'esthétique.


Mais tu ne va pas me dire que toute la reste du C++ est belle,
quand même:-).

Je suis d'accord avec toi en ce qui concerne l'esthétique. Mais
alors, il faudrait changer pas mal de chose -- et on pourrait
récupérer ^ comme opérateur de puissance, parce que l'ou
exclusif s'écrira XOR. Mais ça serait un autre langage, non
C++.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


1 2 3 4