### ----------------------------------------------------
### -- Arithmetic::PaperAndPencil
### -- Licenses: Artistic-2.0
### -- Authors: Jean Forget
### -- File: doc/Description-fr.md
### ----------------------------------------------------
### -- Chunk 4 of 5
7

l → 0         6 2 8          6 2 8
             --------       --------
    1        |      |       |     /|
    2        |      |2      |    / |2
    3        |      |    →  |   /  |
    4        |      |3      |  /   |3
    5        |      |       | /    |
    6        |      |4      |/     |4
             --------       --------
    7
```

* `level = 5` (voir ci-dessous)

* `label = DRA04` code pour le tracé d'une ligne oblique

* `w1l = 1`, `w1c = 6`

* `w2l = 6`, `w2c = 1`

* autres attributs : peu importe

### Champ `level`

Le champ `level`  permet de déterminer quand  les méthodes d'affichage
incluent  l'opération en  cours de  constitution. Plus  la valeur  est
élevée,  plus fréquemment  l'opération  partielle  sera affichée.  Les
valeurs sont :

* 0 affichage uniquement à la fin de l'opération.

* 1  affichage  également  lors  d'un  changement  de  page  (cas  des
multiplications préparées et des divisions préparées).

* 2 affichage lors d'un changement de phase. Pour les multiplications,
par exemple,  il y a  trois phases : la mise  en place, le  calcul des
produits partiels et l'addition finale.

* 3 traitement complet d'un chiffre.  Pour les divisions, il s'agit de
l'ajout  d'un chiffre  au quotient,  avec en  corollaire l'ajout  d'un
reste intermédiaire. Ce mécanisme se faisant par essais et erreurs, le
niveau 3 est déclenché lors du dernier essai, celui qui est fructueux.

* 4 pour  les méthodes avec  essais et  erreur, comme la  division, ce
niveau conclut un essai aboutissant à une erreur.

* 5 pour  l'écriture de  chaque chiffre d'un  produit partiel  ou d'un
reste partiel.

* 6 calcul intermédiaire sans écriture.

Dans le cas de  la conversion d'une base à une autre  par le schéma de
Horner,  l'opération   complète  comporte   plusieurs  multiplications
élémentaires  en  alternance  avec  des  additions  élémentaires.  Les
niveaux de ces multiplications et additions élémentaires sont décalées
par  rapport  aux niveaux  utilisés  dans  une multiplication  ou  une
addition  isolée.  Par exemple,  le  niveau  2, changement  de  phase,
devient  le niveau  5, le  niveau 3,  traitement complet  d'un chifre,
devient le niveau 6 et ainsi de suite.

Pour une  action donnée, la valeur  de `level` dépend de  la nature de
cette action, mais aussi de celle  de l'action suivante. Ainsi, il est
possible d'avoir une action `WRI01` de  niveau 0, si c'est la dernière
action de l'opération ou si elle est suivie d'une action `TITnn`.

### Codes actions particuliers

Ces  codes  ne  sont  pas  directement  liés  à  la  résolution  d'une
opération. Ce sont des actions utilitaires.

| Code  | Explication                                   |
|-------|:----------------------------------------------|
| DRA01 | Ligne verticale                               |
| DRA02 | Ligne horizontale                             |
| DRA03 | Ligne oblique, représentée par des backslashs |
| DRA04 | Ligne oblique, représentée par des slashs     |
| ERA01 | Effacement de caractères                      |
| HOO01 | Crochet sur un dividende                      |
| NXP01 | Changement de page                            |
| TITnn | Titre pour une opération                      |

Pourquoi quatre codes actions différents pour les lignes ? N'aurait-il
pas  été plus  judicieux de  déterminer l'orientation  de la  ligne en
vérifiant si `w1c == w2c` (donc la  ligne est verticale) ou si `w1l ==
w2l` (donc  la ligne  est horizontale) ? Non,  car il y  a le  cas des
lignes n'occupant qu'une  case. Pour de telles lignes, on  a à la fois
`w1c == w2c`, `w1l ==  w2l`, `w1c - w2c = w1l - w2l`  et `w1c - w2c ==
w2l -  w1l`, donc on  ne sait pas s'il  faut écrire un  seul caractère
_pipe_,  un  seul  slash  ou  un seul  backslash  ou  bien  s'il  faut
positionner l'indicateur de soulignement pour un seul caractère.

Le crochet  sur un dividende sert  à repérer la coordonnée  colonne du
premier reste intermédiaire. Au  début, j'avais l'intention d'utiliser
le caractère  `U+0305` (`COMBINING  OVERLINE`), mais mes  essais n'ont
pas été concluants. C'est donc juste une variante de `DRA02`.

Remarques diverses
------------------

Parmi les conseils  pour l'écriture des programmes, il y  a le conseil
proscrivant l'utilisation de valeurs numériques dites « magiques ». Il
faut  les remplacer  par des  constantes  symboliques avec  un nom  en
clair. Je  n'ai pas  cherché à appliquer  ce conseil.  Néanmoins, j'ai
écrit à quelques occasions :

```
  my $zero = Arithmetic::PaperAndPencil::Number.new(:radix($radix), :value<0>);
  my $one  = Arithmetic::PaperAndPencil::Number.new(:radix($radix), :value<1>);
```

Cela allège et cela simplifie la suite des fonctions concernées.

```
    given $result {
      when 'quotient'  { return $zero; }
      when 'remainder' { return $dividend; }
      when 'both'      { return ($zero, $dividend); }
    }
    [...]
          $act-quo ☈-= $one;
```
Pour mémoire, il est assez fréquent que
[ce conseil soit détourné de son but légitime](https://thedailywtf.com/articles/constant-adventure).

Possibilités laissées de côté
=============================

Ce texte sert à commenter ce que  j'ai fait, mais aussi ce que je n'ai
pas fait.

Fonctionnalités laissées de côté
--------------------------------

### Nombres à virgule

Au tout début, j'avais envisagé de  faire des calculs avec des nombres
à virgule.  Je pense que  cela aurait nécessité l'ajout  de nombreuses
lignes de code,  pour un gain mineur. Les nombres  dans ce module sont
donc des nombres entiers.

### Preuve par 9

Mon livre de calcul des années  1960 contenait une leçon sur la preuve
par 9,  mais mon instituteur  refusait de nous l'enseigner.  La preuve
par 9 peut  prouver qu'il y a une erreur  de calcul, vraisemblablement
dans  l'opération, mais  éventuellement  dans la  preuve elle-même.  À
l'inverse, elle ne peut pas prouver que l'opération est correcte. Elle
peut tout au plus _suggérer_ que l'opération _pourrait être_ correcte.
Il est  très facile d'obtenir un  faux positif, il suffit  d'écrire un
chiffre dans une mauvaise colonne et le tour est joué.

Je  n'ai pas  appris  la preuve  par 9  (officiellement),  donc je  ne
l'implémente pas dans mon module.

### Bouliers

Pendant un  certain temps,  j'ai envisagé d'inclure  le calcul  sur un
boulier de type _Suan Pan_  ou _Soroban_. Comme la visualisation était
à refaire  complètement, et comme  les méthodes de calcul  sur boulier
avaient assez peu de points communs avec les méthodes papier + crayon,
j'ai abandonné cette idée. Si nécessaire, cela fera partie d'un module
séparé. Module écrit par quelqu'un d'autre selon toute vraisemblance.

D'un autre côté, certaines variantes lues dans _NWNS_ ou dans _HAL_ et
codées dans le  module pourraient être des méthodes  utilisées sur les
bouliers  et adaptées  par  l'auteur du  livre  pour l'impression  sur
papier.

### Multiplication en croix

Cette méthode est brièvement décrite dans  _NWNS_ pages 441 et 442. K.
Menninger donne  un exemple  pour le  produit de  deux nombres  à deux
chiffres et signale lapidairement que cette méthode peut s'étendre, avec difficulté,
à deux nombres à  quatre chiffres. Soit à calculer `34  × 78`. On pose
les nombres ainsi :

```
3 4
|×|
7 8
```

Le calculateur  multiplie les unités, « 4  × 8 =  32, je pose 2  et je
retiens 3 ». Puis il multiplie les chiffres en croix et additionne les
résultats avec  la retenue : « 3 fois  8, 24, 7  fois 4, 28, 24  et 28
font 52, et 3 font 55, je pose  5 et je retiens 5 ». Puis il multiplie
les chiffres  des dizaines : « 3 fois  7, 21, et 5,  26 ». Le résultat
final est donc 2652.

Cette méthode est  prévue pour des facteurs de 4  chiffres au maximum,
alors que  mon but  est de présenter  des multiplications  de longueur
quelconque. D'autre part, elle nécessite d'additionner mentalement des
nombres à deux chiffres, comme 24 et 28 dans l'exemple, alors que j'ai
décidé de  limiter les additions  mentales pour qu'un nombre  au moins
ait un seul chiffre. Je laisse donc cette variante de côté.

### Autres opérations arithmétiques

Le but  primaire du  module est  de présenter  le calcul  d'une racine
carrée. Il va de soi que le module aurait été incomplet s'il n'y avait
pas  eu  les  quatre   opérations  de  base,  addition,  soustraction,
multiplication  et division.  En plus  de cela,  on peut  envisager la
décomposition en  facteurs premiers,  la conversion  d'une base  à une
autre soit par calcul d'un polynôme avec le schéma de Horner, soit par
des divisions  successives et enfin  le calcul du PGCD  également avec
des divisions  successives, c'est-à-dire l'algorithme  d'Euclide. J'ai
définitivement abandonné  la décomposition en facteurs  premiers, j'ai
définitivement décidé d'inclure la conversion  par le schéma de Horner
et par divisions en cascade, ainsi que le calcul du PGCD.

Pour  mémoire,  la  décomposition  en facteurs  premiers  de  28,  par
exemple, donne :

```
28 | 2
14 | 2
 7 | 7
 1 |
```

Avec, sur des feuilles séparées, la division de 28 par 2, de 14 par 2,
de 7 par  2 (avec un reste),  de 7 par 3  (avec un reste), de  7 par 5
(avec encore un reste) et de 7 par 7 (pas de reste, ouf !). Comme cela
nécessite de nombreuses feuilles  séparées, la visualisation n'est pas
très commode et j'ai abandonné cette idée.

Dans _NWNS_ à la page 442, K. Menninger décrit encore un autre type de
multiplication, la multiplication par  facteurs. Il prend l'exemple de
la multiplication `23 × 14`. La première étape de cette multiplication
consiste à multiplier  23 par 2, ce  qui donne 46 et  la seconde étape
consiste  à multiplier  46  par 7,  ce qui  donne  322. Cette  méthode
nécessite  d'avoir  un  multiplicateur   avec  des  facteurs  premiers
suffisamment  petits  et elle  requiert  une  extraction des  facteurs
premiers avant de commencer la  multiplication. J'ai donc laissé cette
méthode de côté.

### Bases de numération 37 et au-delà

J'ai  posé la limite à  la base de
numération 36, parce que notre  alphabet comporte 26 lettres, que l'on
peut ajouter aux  10 chiffres. Il est donc  impossible d'aller au-delà
de la base  36 avec ce système. Or, il  existe deux bases importantes,
la base  60 (pour les  heures, minutes,  secondes et pour  les degrés,
minutes d'angle et secondes d'angle) et la base 256 (pour les adresses
IPv4, entre  autres). C'est seulement après  avoir commencé l'écriture
du module que  je me suis rappelé que l'on  peut représenter un nombre
en base 60  ou en base 256 avec les  dix chiffres de 0 à 9.  Il y a la
notation  pointée  et  il  y  a la  notation  que  j'appellerai  « codé
décimal » (par analogie avec le DCB, décimal codé binaire).

| domaine | base 10    | notation pointée | codé décimal |
|:--------|-----------:|:----------------:|-------------:|
| heure   | 71120      |  19:45:20        | 194520       |
| heure   | 68585      |  19:3:5          | 190305       |
| IPv4    | 2130706433 | 127.0.0.1        | 127000000001 |
| IPv4    | 3232235777 | 192.168.1.1      | 192168001001 |

Comme vous pouvez  le voir, la notation pointée  utilise un séparateur
qui  est  habituellement  le  point,  mais  qui  peut  être  un  autre
caractère, comme le  deux-points pour les heures.  Vous avez peut-être
été surpris par la notation "codé décimal" de l'adresse IPv4 et par la
notation en  base 10. La  notation en base  10 est très  peu utilisée,
mais  elle est  parfaitement valide.  Vous pouvez  très bien  demander
l'adresse  `http://3232235777`  sur  votre navigateur.  Ou  bien  vous
pouvez pinguer l'adresse `2130706433`. En revanche, la
notation  "codé décimal"  n'est pas  utilisée, mais  cela pourrait  se
faire. Le gros problème à résoudre est qu'il y a une ambiguïté entre la
notation en base 10 et la notation "codé décimal".

J'ai laissé tomber  d'autres variantes de bases de numération.  Il y a
les bases mixtes,  comme la base `20-18` utilisée dans  le compte long
du calendrier maya, ou la base factorielle, présentée dans
[xkcd](https://xkcd.com/2835/).
Il y a  également la base `i-1`  créée par W. Penney  et présentée par
D.E. Knuth  dans le chapitre  4 de  _The Art of  Computer Programming_
(pages 189 et  190), qui utilise seulement les chiffres  `0` et `1` et
qui permet de  couvrir tous les points à coordonnées  entières dans le
plan  complexe et  non pas  seulement sur  la demi-droite  des nombres
positifs. Et il y a le  système ternaire équilibré, un système en base
3, mais utilisant  les chiffres `0`, `1` et  « `1`-barre », ce dernier
ayant une valeur négative (système présenté par D.E. Knuth pages 190 à
192).

Une  dernière  remarque.  Habituellement,  lorsque  l'on  mélange  les
lettres majuscules et  les chiffres, on omet  délibérément les lettres
« O »  et « I »  au prétexte  qu'elles ressemblent  trop aux  chiffres
« 0 »  et  « 1 ». Voyez  par  exemple  les plaques  minéralogiques  en
France. Dans ce module, je les ai  conservées. Et en fait, de la façon
dont mon navigateur est configuré, j'ai plus de mal à différencier les
« 8 » et  les « B » qu'à  différencier les « 0 »  et les « O »  ou les
« 1 » et les « I ».

### Extensions des opérations arithmétiques

Les   opérations   arithmétiques   s'étendent   à   d'autres   entités
mathématiques, comme les vecteurs ou les matrices. Si les additions et
les  soustractions   de  matrices  sont  simples   à  comprendre,  les
multiplications sont  plus évoluées et plus  intéressantes. Néanmoins,
cela  ne  colle  pas  au  présent  module.  De  même,  les  additions,
soustractions  et  multiplications sur  les  polynômes  sont aisées  à
comprendre, mais  la division  est plus  intéressante à  apprendre et,
avec  elle, l'extraction  du PGCD  avec l'algorithme  d'Euclide. Comme
pour les matrices,  cela ne s'intègre pas dans le  présent module. Ces
opérations restent donc en dehors de ce module.

Choix techniques abandonnés
---------------------------

### Structure de la classe `Arithmetic::PaperAndPencil::Action`

Reprenons l'exemple de l'action :

```
        c → 0 123456 7     0 123456 7

l → 0         6 2 8          6 2 8
             --------       --------
    1        | / / /|       |1/ / /|
    2        |/ / / |2      |/2/ / |2
    3        | / / /|    →  | / / /|
    4        |/ / / |3      |/ / / |3
    5        | / / /|       | / / /|
    6        |/ / / |4      |/ / / |4
             --------       --------
    7
```

L'instance correspondante de `A::PP::Action` est constituée de :

* `level = 5`

* `label = MUL01` code pour le message "#1# fois #2#, #3#"

* `val1 = 6`, `val2 = 2`, `val3 = 12` pour un message final "6 fois 2, 12"

* `r1l = 0`, `r1c = 1`, `r1val = 6`, `r1str = False`

* `r2l = 2`, `r2c = 7`, `r1val = 2`, `r1str = False`

* `w1l = 1`, `w1c = 1`, `w1val = 1`

* `w2l = 2`, `w2c = 2`, `w2val = 2`

Initialement,  j'avais  prévu  de  représenter cela  par  5  instances
différentes de l'objet `A::PP::Action` :

1. lire le chiffre 6 du multiplicande (`level = 6`),

2. lire le chiffre 2 du multiplicateur (`level = 6`),

3. dire le message "6 fois 2, 12" (`level = 6`),

4. écrire le chiffre 1 du produit partiel (`level = 6`),

5. écrire le chiffre 2 du produit partiel (`level = 5`).

Chaque instance aurait  contenu une seule coordonnée  ligne, une seule
coordonnée  colonne   et  une  seule  valeur   (sauf  pour  l'instance
correspondant au message prononcé  verbalement). Le tout avec d'autres
codes  que `MUL01`,  tels que  `WRI00`  (qui existe)  et `REA00`  (qui
aurait représenté une lecture).

Finalement,  c'est mieux  de  tout  mettre dans  la  même instance  de
`A::PP::Action`. Il  reste encore un cas  de figure où une  action est
découpée en deux  instances. C'est le cas lorsqu'un  calcul se conclut
par « Je pose 2 et je retiens 1 ». Il y a une instance pour le message
de  calcul  « 6  fois  2,  12 »   avec  la  lecture  des  chiffres  du
multiplicateur et  du multiplicande  et il  y a  une instance  pour le
message « Je pose... » avec l'écriture du produit intermédiaire.

### Bases de données

Au lieu d'utiliser des objets et  des classes en mémoire vive, j'avais
envisagé de  stocker le tout dans  des tables SQL. Cela  aurait ajouté
des problèmes d'infrastructure et de logisitique inutiles.

### Formats de sortie

J'ai eu l'intention d'utiliser d'autres  formats de sortie, en plus de
HTML :  texte  seul,  L<sup>A</sup>T<sub>E</sub>X  +  Metapost,  voire
curses ou GIMP ou même un  format vidéo (pourquoi pas, après tout). Il
se    peut   qu'un    jour   ou    l'autre   je    code   le    format
L<sup>A</sup>T<sub>E</sub>X  + Metapost,  mais les  autres formats  ne
sont pas à l'ordre du jour.

### Addition « en zigzag »

L'addition normale porte sur des nombres alignés à droite, c'est-à-dire
alignés sur leur chiffre des unités. Par exemple :

```
   2512
   1844
   1256
   ----
   5612
```

Néanmoins, pour les besoins de la multiplication, j'avais envisagé une
variante « en zigzag » de l'addition, les nombres n'étant plus alignés
les uns avec les autres. Quelques exemples :

```
    2512       2512          2512
   1844      1844           1884
    1256       1256        1256
   -----     ------        ------
   22208     188168        146952
```

L'addition  en zigzag  aurait été  une méthode  privée, hors  de l'API
publique.

Finalement,  j'ai trouvé  un  autre  moyen, qui  consiste  à créer  un
tableau de listes où les chiffres figurent individuellement, sans lien
avec leur nombre d'origine. Un avantage  de ce nouveau moyen est qu'il
est compatible avec les  additions obliques des variantes `jalousie-A`
et `jalousie-B`  de la multiplication,  ce qui  n'était pas le  cas de
l'addition en zigzag.

### Modules CSV et modules HTML

Je sais qu'analyser du HTML avec des  regex n'est pas bien du tout. Or
la méthode `html`  du module `Arithmetic::PaperAndPencil` écrit une  chaîne en pseudo-HTML,
puis  traite cette  chaîne avec  des regex  pour générer  du véritable
HTML. Le point à retenir est que la première étape consiste à créer du
_pseudo_-HTML,  sans  aucune  fonctionnalité  avancée  telle  que  les
attributs  HTML,  les   commentaires  HTML  et  ainsi   de  suite.  Le
pseudo-HTML est suffisamment simple pour  pouvoir être traité avec des
regex.

De la même manière, je n'ai pas trouvé de module d'analyse de CSV à ma
convenance, donc j'ai  écrit ma propre analyse de CSV  avec des regex.
D'un  autre côté,  je  n'ai pas  besoin  des fonctionnalités  évoluées
telles  que  des  chaînes   entre  guillemets,  ou  l'échappement  des
points-virgules et  d'autres méta-caractères.  Donc pour  cette tâche,
comme  pour  la conversion  de  pseudo-HTML  en véritable  HTML,  j'ai
utilisé des regex élémentaires.

Considérations diverses
=======================

Conversion d'un nombre de base 10 en base _b_
---------------------------------------------

On connaît bien les premières décimales de  π ou de e en base 10. Mais
qu'en   est-il   en   base   12,   ou   en   base   16 ?   Le   module
`Arithmetic::PaperAndPencil` permet de répondre  à ces questions, mais
avec  quelques   étapes  pas  forcément  intuitives   pour  contourner
certaines limites du module.

Prenons l'exemple  de π  et de  la base  16. La  première étape  de la
réflexion ne s'applique pas à la base  12, mais seulement à la base 16
(ainsi que la base  8 et la base 2). Raku,  comme de nombreux langages
de programmation,  permet en quelque  sorte une conversion de  base de
numération avec

```
$out = sprintf("%x", $in);
```

La contrainte étant que `$in` doit être un entier, ce qui n'est pas le
cas de π (ou de e). Donc on biaise en utilisant

```
sub conv16-pi(Int $scale) {
  sprintf("%x",  π × 16 ** $scale);
}
```

Et  en insérant  la  virgule décimale  ou le  point  décimal après  le
chiffre « 3 » initial.  Cette fonction est valide  jusqu'à 13 chiffres
après la virgule en base 16  mais les chiffres à partir du quatorzième
sont tous à  zéro, ce qui est  erroné (le treizième est  à zéro aussi,
mais c'est normal). C'est dû au  fait que la constante `π` est définie
avec  15 chiffres  décimaux  après  la virgule,  ce  qui correspond  à
environ 13 chiffres hexadécimaux après la virgule.

Rappel : une  relation bien connue est  « 2^10 ≈ 10^3 ». On  en déduit
aisément  que « 16^5  ≈ 10^6 »,  donc une  partie fractionnaire  de 12
chiffres  décimaux donnera  une  partie fractionnaire  de 10  chiffres
hexadécimaux  corrects  et une  partie  fractionnaire  de 18  chiffres
décimaux donnera une partie  fractionnaire de 15 chiffres hexadécimaux
corrects.

Cette  solution, qui  n'utilise pas  `Arithmetic::PaperAndPencil`, est
invalide au-delà du treizième chiffre  fractionnaire et, de plus, elle
est  inapplicable  pour  les  autres bases  de  numération  (sauf  cas
particuliers, 2 et 8).

Le  module  `Arithmetic::PaperAndPencil`   permet  de  dépasser  cette
limite. On a  recours à deux facteurs  de mise à l'échelle  et à trois
variables

* `$factor16` qui vaut « 16^_n1_ »,
* `$factor10` qui vaut « 10^_n2_ »,
* `$pi-x10` qui vaut « π × $factor10 »,
* `$pi-x16` qui vaut « π × $factor16 »,
* `$pi-x10-x16` qui vaut « π × $factor10 × $factor16 ».

La fonction à utiliser est donc :

```
sub conv-pi(Int $scale) {
  # https://en.wikipedia.org/wiki/Pi#Approximate_value_and_digits
  # https://oeis.org/A000796
  my Str $pi-alpha = '314159265358979323846264338327950288419716939937510';

  my Int $scale10 = ($scale × 6 / 5).ceiling;
  my Arithmetic::PaperAndPencil::Number $factor16 .= new(:radix(16), :value('1' ~ '0' x $scale));
  my Arithmetic::PaperAndPencil::Number $factor10 .= new(:radix(10), :value('1' ~ '0' x $scale10));
  $factor16 = $operation.conversion(number => $factor16, radix => 10);
  $factor10 = $operation.conversion(number => $factor10, radix => 16);

  my Arithmetic::PaperAndPencil::Number $pi-x10 .= new(:radix(10), :value($pi-alpha.substr(0, 1 + $scale10)));
  my Arithmetic::PaperAndPencil::Number $pi-x10-x16 = $operation.multiplication(multiplicand => $pi-x10, multiplier => $factor16);
  $pi-x10-x16 = $operation.conversion(number => $pi-x10-x16, radix => 16);
  my Arithmetic::PaperAndPencil::Number $pi-x16 = $operation.division(dividend => $pi-x10-x16, divisor => $factor10);
  return $pi-x16.value;
}
```

Il est facile d'adapter cette  fonction à d'autres bases de numération
comme la base 12.  Le point le plus délicat est  de trouver par quelle
valeur remplacer la fraction « 6/5 » permettant de calculer le facteur
d'échelle pour la base 10.

Le  programme   correspondant  est   disponible  dans   le  répertoire
`examples` de la distribution.

Cela dit, si Raku ne peut pas faire de calculs étendus avec des `Num`,
il peut en faire avec des entiers, les `Int` natifs étant des `BigInt`
en  toutes  choses sauf  le  nom.  Donc  la  fonction peut  être  très
légèrement simplifiée avec :

```
sub conv-pi(Int $scale) {
  # https://en.wikipedia.org/wiki/Pi#Approximate_value_and_digits
  # https://oeis.org/A000796
  my Str $pi-alpha = '314159265358979323846264338327950288419716939937510';

  my Int $scale10 = ($scale × 6 / 5).ceiling;
  my Arithmetic::PaperAndPencil::Number $factor16 .= new(:radix(10), :value((16 ** $scale).Str));
  my Arithmetic::PaperAndPencil::Number $factor10 .= new(:radix(10), :value('1' ~ '0' x $scale10));
  $factor10   = $operation.conversion(number => $factor10  , radix => 16);

  my Arithmetic::PaperAndPencil::Number $pi-x10   .= new(:radix(10), :value($pi-alpha.substr(0, 1 + $scale10)));
  my Arithmetic::PaperAndPencil::Number $pi-x10-x16 = $operation.multiplication(multiplicand => $pi-x10, multiplier => $factor16);
  $pi-x10-x16 = $operation.conversion(number => $pi-x10-x16, radix => 16);
  my Arithmetic::PaperAndPencil::Number $pi-x16 = $operation.division(dividend => $pi-x10-x16, divisor => $factor10);
  return $pi-x16.value;
}
```

et on y gagne quelques cycles de CPU.

Dans le  cas du nombre  d'or φ, il n'est  pas nécessaire de