%MAX
La plus grande de plusieurs valeurs
Renvoie la plus grande des valeurs passées (nombres, dates ou texte).
Syntaxe
%MAX(valeur1 : valeur2 {: valeur3 …})
valeur1, valeur2…- Deux valeurs ou plus, de même nature : des nombres (types numériques mélangés acceptés), des dates ou du texte.
- Résultat
- La plus grande des valeurs, avec le type de l'expression (un nombre pour des nombres, une date pour des dates, du texte pour du texte).
À quoi ça sert
Remplace un if a > b suivi d'une affectation. On l'emploie surtout pour borner une valeur : %max(solde : 0) ramène un solde négatif à zéro. Avec des dates, on obtient la plus récente sans écrire de test.
Exemple 1 : Nombres et dates
**free
// %MAX : la plus grande de plusieurs valeurs, nombres ou dates.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s solde packed(9:2) inz(-320.00);
dcl-s achat1 packed(9:2) inz(1250.50);
dcl-s achat2 packed(9:2) inz(98000.00);
dcl-s achat3 packed(9:2) inz(45.10);
dcl-s cree date inz(d'2019-06-30');
dcl-s modifie date inz(d'2024-01-08');
dcl-s livre date inz(d'2021-11-02');
snd-msg 'Plus gros achat : ' + %char(%max(achat1 : achat2 : achat3));
// Ramener un solde negatif a zero.
snd-msg 'Solde sans negatif : ' + %char(%max(solde : 0));
// Avec des dates : la plus recente.
snd-msg 'Derniere date : ' + %char(%max(cree : modifie : livre));
// Melange de types numeriques.
snd-msg 'Melange : ' + %char(%max(achat1 : 300 : 1.25));
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Plus gros achat : 98000.00
Solde sans negatif : .00
Derniere date : 2024-01-08
Melange : 1250.50
Le plus gros achat est 98 000,00. %max(solde : 0) remplace le solde négatif (-320,00) par 0, affiché .00 par %char. Avec trois dates, on obtient la plus récente (2024-01-08). Les types numériques peuvent se mélanger : zone décimale, entier et constante décimale.
Exemple 2 : Du texte, dans l'ordre EBCDIC
**free
// %MAX sur du texte : l'ordre est celui de l'EBCDIC, pas celui du dictionnaire.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s a char(10) inz('Brest');
dcl-s b char(10) inz('Lyon');
snd-msg 'Brest / Lyon : [' + %max(a : b) + ']';
// Une minuscule est plus petite qu'une majuscule.
snd-msg 'brest / Lyon : [' + %max('brest' : 'Lyon') + ']';
snd-msg 'zoe / Alice : [' + %max('zoe' : 'Alice') + ']';
// Un chiffre est plus grand qu'une lettre.
snd-msg '9 rue / Zola : [' + %max('9 rue' : 'Zola') + ']';
// Solution : mettre les deux textes en majuscules avant de comparer.
snd-msg 'ZOE / ALICE : [' + %max(%upper('zoe') : %upper('Alice')) + ']';
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Brest / Lyon : [Lyon ]
brest / Lyon : [Lyon]
zoe / Alice : [Alice]
9 rue / Zola : [9 rue]
ZOE / ALICE : [ZOE]
« Lyon » est plus grand que « Brest ». Mais « brest » en minuscules est plus petit que « Lyon », et « zoe » plus petit que « Alice » : en EBCDIC, les minuscules sont avant les majuscules, et les chiffres après les lettres (« 9 rue » est plus grand que « Zola »). En passant les deux textes par %upper, on retrouve l'ordre alphabétique attendu.
Les zones char(10) gardent leurs blancs de fin dans le résultat ([Lyon ]), pas les constantes.
Le piège
Sur du texte, « plus grand » suit l'EBCDIC, pas le dictionnaire. Une minuscule vaut moins qu'une majuscule, un chiffre plus qu'une lettre : %max('zoe' : 'Alice') renvoie Alice, alors qu'on attendrait zoe. Pour comparer des noms saisis à la main, on met les deux côtés en majuscules avec %upper avant de comparer, comme dans le second exemple.