%XFOOT
Somme des éléments d'un tableau
Additionne tous les éléments d'un tableau numérique et renvoie le total.
Syntaxe
%XFOOT(tableau)
tableau- Un tableau numérique. On peut passer une partie du tableau avec
%subarr. - Résultat
- Un nombre : la somme des éléments. Dans une expression, le total n'est pas tronqué à la taille d'un élément. Un tableau vide, ou un tableau
dim(*auto)sans élément, donne 0.
À quoi ça sert
Sans %xfoot, il faut une boucle et une zone de cumul pour totaliser un tableau. Ici, une ligne suffit : total des factures d'un client, total d'une colonne de montants, moyenne (%xfoot(tab) / %elem(tab)).
Avec dim(*auto), seuls les éléments ajoutés comptent, ce qui donne des moyennes justes sans compteur à part.
Exemple 1 : Total, sous-total et moyenne
**free
// %XFOOT : somme des elements d'un tableau numerique.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s facture packed(9:2) dim(*auto : 50);
dcl-s total packed(11:2);
dcl-s moyenne packed(11:2);
facture(*next) = 1250.50;
facture(*next) = 45.10;
facture(*next) = 98000.00;
facture(*next) = 320.00;
total = %xfoot(facture);
snd-msg 'Total des factures : ' + %char(total);
// Seulement les elements 2 a 3, avec %subarr.
snd-msg 'Elements 2 et 3 : ' + %char(%xfoot(%subarr(facture : 2 : 2)));
// Moyenne : somme divisee par le nombre d'elements de dim(*auto).
moyenne = %xfoot(facture) / %elem(facture);
snd-msg 'Moyenne : ' + %char(moyenne);
// Tableau vide : la somme est 0.
%elem(facture) = 0;
snd-msg 'Tableau vide : ' + %char(%xfoot(facture));
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Total des factures : 99615.60
Elements 2 et 3 : 98045.10
Moyenne : 24903.90
Tableau vide : .00
Le tableau dim(*auto) reçoit quatre factures. %xfoot(facture) les additionne toutes (99 615,60), %xfoot(%subarr(facture : 2 : 2)) seulement les éléments 2 et 3. La moyenne divise par %elem, donc par 4. Une fois le tableau vidé avec %elem(facture) = 0, la somme est 0.
Exemple 2 : Somme plus grande qu'un élément
**free
// %XFOOT : la somme n'est pas tronquee, mais la zone qui la recoit doit etre assez grande.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s petit packed(3:0) dim(3);
dcl-s cible packed(3:0);
dcl-s large packed(9:0);
petit(1) = 999;
petit(2) = 999;
petit(3) = 999;
// Dans une expression, la somme (2997) depasse la taille d'un element sans probleme.
snd-msg 'Somme dans un message : ' + %char(%xfoot(petit));
large = %xfoot(petit);
snd-msg 'Dans packed(9:0) : ' + %char(large);
// Dans packed(3:0), la somme ne tient pas : le programme s'arrete.
cible = %xfoot(petit);
snd-msg 'Cette ligne n''est jamais atteinte';
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Somme dans un message : 2997
Dans packed(9:0) : 2997
Erreur : RNQ0103 - (C G D F) Cible pour opération numérique trop petite pour contenir résultat.
Trois éléments packed(3:0) valent 999 : le total 2 997 s'affiche sans problème dans un message et tient dans un packed(9:0). Mais l'affecter à un packed(3:0) arrête le programme (RNQ0103).
Le piège
Le total doit tenir dans la zone qui le reçoit. La somme est calculée en pleine précision, mais l'affectation à une zone trop petite (celle des éléments, par exemple) fait échouer le programme avec RNQ0103, comme le montre le second exemple. Il faut prévoir une zone de résultat plus large que les éléments : plus de chiffres devant la virgule que l'élément, en fonction du nombre d'éléments à additionner.
Autre détail : sur un tableau à dimension fixe, les éléments jamais remplis valent 0 et ne gênent pas la somme. Ils n'entrent pas dans le calcul d'une moyenne faite avec %elem : la division se fait par la dimension, pas par le nombre d'éléments remplis.