Aller au contenu

%HIVAL

Plus grande et plus petite valeur d'une zone

%HIVAL renvoie la plus grande valeur que peut contenir la zone donnée, %LOVAL la plus petite.

Syntaxe

%HIVAL(zone)
%LOVAL(zone)
zone
Une zone numérique, date, heure, horodatage ou caractère. Seuls son type et sa taille comptent, pas son contenu.
Résultat
Une valeur du même type et de la même taille que la zone : pour un packed(7:2), -99999.99 et 99999.99 ; pour un int(10), -2147483648 et 2147483647 ; pour une date, 0001-01-01 et 9999-12-31.

À quoi ça sert

Pour chercher le plus petit et le plus grand élément d'une série, il faut partir de valeurs qui seront forcément remplacées par le premier élément lu. On met le minimum à %HIVAL et le maximum à %LOVAL. Sans cela, on doit écrire en dur 9999999.99, un chiffre qui devient faux si on agrandit la zone : %HIVAL s'adapte tout seul à sa taille.

Exemple 1 : Solde le plus bas et le plus haut

**free
// %HIVAL et %LOVAL : amorcer une recherche de plus petite et de plus grande valeur.
ctl-opt dftactgrp(*no) actgrp(*new) alwnull(*usrctl);

dcl-f client keyed usage(*input);

dcl-s mini packed(9:2);
dcl-s maxi packed(9:2);

// Le minimum part tout en haut, le maximum tout en bas : le 1er solde lu les remplace.
mini = %hival(mini);
maxi = %loval(maxi);
snd-msg 'Depart : mini = ' + %char(mini) + ', maxi = ' + %char(maxi);

setll *loval client;
read client;
dow not %eof(client);
  if solde < mini;
    mini = solde;
  endif;
  if solde > maxi;
    maxi = solde;
  endif;
  read client;
enddo;
close client;

snd-msg 'Solde le plus bas  : ' + %char(mini);
snd-msg 'Solde le plus haut : ' + %char(maxi);

*inlr = *on;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

Depart : mini = 9999999.99, maxi = -9999999.99
Solde le plus bas  : -320.00
Solde le plus haut : 98000.00

Les deux variables sont amorcées avec les valeurs extrêmes de leur taille (9999999,99 et -9999999,99). La lecture du fichier les remplace au premier client, puis au fil de la boucle. Résultat : -320,00 (Leroy SARL) et 98 000,00 (Bernard Transports).

Exemple 2 : Les extrêmes selon le type

**free
// %HIVAL et %LOVAL : la valeur extreme depend du type ET de la taille de la zone.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s montant packed(7:2);
dcl-s numero  zoned(5:0);
dcl-s petit   int(5);
dcl-s moyen   int(10);
dcl-s grand   int(20);
dcl-s octet   uns(3);
dcl-s jour    date;
dcl-s heure   time;
dcl-s code    char(3);

snd-msg 'packed(7:2) : ' + %char(%loval(montant)) + ' a ' + %char(%hival(montant));
snd-msg 'zoned(5:0)  : ' + %char(%loval(numero)) + ' a ' + %char(%hival(numero));
snd-msg 'int(5)      : ' + %char(%loval(petit)) + ' a ' + %char(%hival(petit));
snd-msg 'int(10)     : ' + %char(%loval(moyen)) + ' a ' + %char(%hival(moyen));
snd-msg 'int(20)     : ' + %char(%loval(grand)) + ' a ' + %char(%hival(grand));
snd-msg 'uns(3)      : ' + %char(%loval(octet)) + ' a ' + %char(%hival(octet));
snd-msg 'date        : ' + %char(%loval(jour)) + ' a ' + %char(%hival(jour));
snd-msg 'time        : ' + %char(%loval(heure)) + ' a ' + %char(%hival(heure));

// Pour une zone caractere, on compare avec *HIVAL / *LOVAL (octets x'FF' et x'00').
code = %hival(code);
snd-msg 'char(3) egal a x''FFFFFF'' ? ' + %char(code = x'FFFFFF');
code = %loval(code);
snd-msg 'char(3) egal a x''000000'' ? ' + %char(code = x'000000');

*inlr = *on;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

packed(7:2) : -99999.99 a 99999.99
zoned(5:0)  : -99999 a 99999
int(5)      : -32768 a 32767
int(10)     : -2147483648 a 2147483647
int(20)     : -9223372036854775808 a 9223372036854775807
uns(3)      : 0 a 255
date        : 0001-01-01 a 9999-12-31
time        : 00.00.00 a 24.00.00
char(3) egal a x'FFFFFF' ? 1
char(3) egal a x'000000' ? 1

Chaque type a ses bornes : un int(5) va de -32768 à 32767, un uns(3) de 0 à 255, un packed(7:2) de -99999,99 à 99999,99. Pour une zone caractère, %HIVAL remplit la zone d'octets x'FF' et %LOVAL d'octets x'00' : le test le confirme.

Le piège

Les bornes dépendent de la taille déclarée de la zone. Un packed(7:2) s'arrête à 99999,99 (exemple 2), un packed(9:2) à 9999999,99 (exemple 1). N'écrivez donc jamais ces chiffres en dur : ils deviendraient faux si la zone change de taille.

Pour une zone caractère, la valeur est faite d'octets x'FF' (ou x'00'), qui ne s'affichent pas : comparez-la, mais ne l'envoyez pas dans un message.