Licence CC BY-NC-ND

La Texnique : Améliorer les commandes comme \cos et \sin ?

Argument optionnel, parenthèses automatiques et même plus

Une chose qui peut frustrer beaucoup de personnes avec les commandes comme \sin et \cos est que les parenthèses (ou autres délimiteurs), si elles sont voulues, doivent être placées à la main. C’est en particulier embêtant si on veut une taille automatique de délimiteur avec \left et \right.

\[
   \sin(x) = \sin\left(\frac{1}{2}\right).
\]

Nous, on aimerait bien pouvoir écrire ça.

\[
   \sin{x} = \sin{\frac{1}{2}}.
\]

Donc, ça peut être plutôt cool de créer des commandes qui se comportent de cette manière. Nous n’allons donc pas utiliser \DeclareMathOperator qui nous crée des commandes qui se comportent comme \sin, mais nous allons créer notre propre commande qui utilise \operatorname. Par exemple, ici, nous créons une commande \ex.

% Inclure amsmath (ou mieux, inclure mathtools).

\newcommand{\ex}[1]{
   \operatorname{ex}\left(#1\right)
}

\[
   \ex{2} \neq \ex{1} + \ex{1}.
\]

Cependant, nous perdons quelque chose que nous avions avec \sin et avec les commandes créées avec \DeclareMathOperator plus généralement : nous ne pouvons pas écrire le nom de la fonction sans rien d’autre. Le code suivant ne fonctionne pas.

La fonction $\cos$ est paire, mais pas $\ex$.

De plus, les parenthèses sont toujours placées et donc nous ne pouvons pas obtenir un résultat comme cosx\cos x avec notre commande \ex.

$x \mapsto \cos x$ est paire, mais pas $x \mapsto \ex x$. 

Nous perdons donc en flexibilité. En fait, ce qui serait bien, c’est une commande qui regarde si elle a un argument et agit en fonction de sa présence.

\[
  \cos, \cos 0, \cos(0), \cos{0}, 
  \cos{\frac{1}{2}}, \cos \frac{1}{2}.
\]

Avec ce code, on voudrait obtenir ce résultat.

cos,cos0,cos(0),cos(0),cos(12),cos12. \cos, \cos 0, \cos(0), \cos\left(0\right), \cos\left(\frac{1}{2}\right), \cos \frac{1}{2}.

Pour ce faire, nous allons utiliser la commande \NewDocumentCommand du package xparse pour créer une commande qui prend en paramètre optionnel entre accolades. Nous pourrions choisir de prendre cet argument entre parenthèses, mais pour des raisons de cohérence je préfère garder mon argument entre accolades.

\NewDocumentCommand{\ex}{g}{
   \operatorname{ex}
   \IfNoValueF{#1}{\left(#1\right)}
}

\[
   \ex, \ex 0, \ex(0), \ex{0}, 
   \ex{\frac{1}{2}}, \ex \frac{1}{2}.
\]
Redéfinition de \left et \right

Lorsqu’on utilise \left et \right une espace fine est placé avant le délimiteur ; voyez la différence entre \sin(x), sin(x)\sin(x), et \sin\left(x\right), sin(x)\sin\left(x\right). Nous allons redéfinir les deux commandes pour supprimer ces espaces.

\let\originalleft\left
\let\originalright\right
\renewcommand{\left}{\mathopen{}\mathclose\bgroup\originalleft}
\renewcommand{\right}{\aftergroup\egroup\originalright}

Et là on a gagné. Mais comme on est des gens vraiment géniaux, on va aller encore plus loin. Vous voyez la commande \sqrt ; elle prend en paramètre facultatif qui est alors mis en exposant. Et si on faisait pareil ? Ce serait cool d’écrire \ex[2]{3} et d’obtenir ex2(3)\operatorname{ex}^2(3). En plus, ce n’est pas vraiment compliqué avec xparse.

\NewDocumentCommand{\ex}{og}{
   \operatorname{ex}
   \IfNoValueF{#1}{^{#1}}
   \IfNoValueF{#2}{\left(#2\right)}
}

\[
   \ex[2]{3} = \ex^2(3) 
\]

On note qu’on peut même utiliser le symbole ^ si on le désire, l’argument optionnel entre crochets est utile dans le cas où l’on donne un argument entre accolades.

L’étape suivante, pour être vraiment content, consiste à créer une commande \newoperator qui crée une commande à notre place. On va donc, comme dans ce précédent billet, créer une commande qui nous créera des commandes. Elle prendra en paramètre le nom à donner à la commande, et le nom de la fonction (donc le nom à afficher).

\newcommand*\newoperator[2]{
   \expandafter\NewDocumentCommand\csname#1\endcsname{og}{
      \operatorname{#2}
      \IfNoValueF{##1}{^{##1}} 
      \IfNoValueF{##2}{\left(##2\right)}
   }
}

\newoperator{ex}{ex}
\newoperator{xe}{xe}

La fonction $\xe$ est définie de la manière suivante.
Soit $x$ un réel,
\[
   \xe{x} =
   \begin{cases}
      \ex{-x}          & \text{ si $x \geq 0$ }\\
      \ex{\frac{1}{x}} & \text{ sinon }
   \end{cases}
\]

Et finalement, pour quand même répondre au titre et améliorer les commandes \cos et \sin, nous allons écrire une méthode \renewoperator. C’est exactement la commande \newoperator, mais avec \RenewDocumentCommand à la place de \NewDocumentCommand.

\newcommand*\renewoperator[2]{
   \expandafter\RenewDocumentCommand\csname#1\endcsname{og}{
      \operatorname{#2}
      \IfNoValueF{##1}{^{##1}}
      \IfNoValueF{##2}{\left(##2\right)}
   }
}

Et il ne nous reste plus qu’à l’utiliser pour donner un coup de neuf à \cos, \sin et bien d’autres commandes !

Une variante

Contrairement à notre commande \newoperator, la commande \DeclareMathOperator prend en premier argument la commande à définir et pas seulement son nom (donc \ex et pas ex). Je trouve ce comportement plutôt sympathique, notamment parce qu’il permet de bien distinguer la commande qu’on est en train de définir, et le nom qu’elle affichera. On peut donc modifier \newoperator et \renewoperator pour qu’ils fonctionnent de la même manière.

\newcommand*\newoperator[2]{
   \expandafter\NewDocumentCommand
   \csname\expandafter\@gobble\string#\endcsname{og}{
      \operatorname{#2}
      \IfNoValueF{##1}{^{##1}}
      \IfNoValueF{##2}{\left(##2\right)}
   }
}

Notons l’utilisation du symbole @ de la commande \@gobble. Cela signifie que si nous voulons définir cette commande dans un document (et pas dans une classe ou un package), il nous faudra placer cette définition entre \makeatletter et \makeatother.



Aucun commentaire

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte