Aller au contenu

%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.