Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

conversion string->decimal

40 réponses
Avatar
Olivier Berquin
Bonjour tout le monde,

C'est ma première intervention ici.
J'ai recherché dans les anciens messages et n'ait pas trouvé de
solution...

J'ai un formulaire dans lequel l'utilisateur doit encoder un montant
(decimal).
Mon input est au format texte.
Comment puis-je être certain d'avoir un type decimal?

j'ai fait ceci, mais ça me paraît un peu tiré par les cheveux:
$val1 = $montant + 0.001;
$val2 = $val1 - 0.001;
if ($val2 == 0)
{
// Ce n'est pas un nombre...
}

Merci.

Oli.

10 réponses

1 2 3 4
Avatar
Olivier Miakinen
voici ce que j'ai fait:

function my_is_numeric($value)
{
$valeur = preg_match('/^[-+]?[0-9]+([ .s]?[0-9]{3})*([ ,.s]?
[0-9])*?$/' ,$value);


L'expression est équivalente à :
/^[-+]?[0-9]+([.s]?[0-9]{3})*([,.s]?[0-9])*$/

En effet,
1) Il est inutile d'échapper le + dans une classe de caractères
2) Le s inclut déjà l'espace
3) Puisque ta chaîne est « ancrée » à gauche et à droite (^...$) il
est inutile de se préoccuper de « gourmandise » des répétitions (*?)

Et en fait, vu qu'un ([.s]?[0-9]{3}) correspond à trois ([,.s]?[0-9])
ton expression est même équivalente à :
/^[-+]?[0-9]+([,.s]?[0-9])*$/


return ($valeur);
}

Je suis assez large: j'accepte aussi bien le notation US que la FR (et
même un mélange des 2 -- hum).
Bon, je vous l'accorde, ce n'est pas trop "catholique". Mais c'est
pour l'intranet d'une petite société (15 personnes), et l'encodage de
ces montants n'incombera qu'à 3 personnes maximum.
Et il y a une étape de confirmation...


Même s'il y a une étape de confirmation, je pense qu'une syntaxe plus
rigoureuse ne ferait pas de mal, et éviterait aux trois personnes en
question de s'interroger sur ta santé mentale.

Voici ce qui est accepté:
21 252,00
21.252,00
+21252,00
12 521,252.12 (ha ? ben oui... ça marche).
-0
+0
0
0,0
0.0


Et aussi : 3,4.5,7 et 3.4,5.7
Combien valent ces nombres ? Quelque chose entre 3,4 et 3,5 ou quelque
chose entre 34,5 et 34,6 ?

Ce qui ne l'est pas: dès qu'il y a un caractère autre qu'un chiffre...


Voici une suggestion :

$valeur = str_replace(",", ".", $valeur);
$valeur = preg_replace("/[s]/", "", $valeur);
if (preg_match('/^[+-]?[0-9]*.[0-9]*$/, $valeur)) {
// Ok
}

Tu pourrais même remplacer le preg_replace par :
$valeur = preg_replace("/[^0-9.]/", "", $valeur);

Avatar
Mickael Wolff
voici ce que j'ai fait:

function my_is_numeric($value)
{
$valeur = preg_match('/^[-+]?[0-9]+([ .s]?[0-9]{3})*([ ,.s]?
[0-9])*?$/' ,$value);
return ($valeur);
}


Si déjà tu utilises s, utilises d : ça simplifie. Et un conseil :
évites d'utiliser / comme délimiteur d'expression, échapper des / à gogo
peut vite devenir pénible.

'@^[-+]?[d]+([ .s]?[d]{3})*([ ,.s]?[d])*?$@'

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org

Avatar
Olivier Miakinen

if (preg_match('/^[+-]?[0-9]*.[0-9]*$/, $valeur)) {


Pardon, il y a une petite erreur ici car le . devient obligatoire.
Ce serait plutôt :
/^[+-]?[0-9]*.?[0-9]*$/

Ou, en tenant compte de la remarque de Mickael :
/^[+-]?d*.?d*$/

En revanche, je ne suis pas d'accord avec Mickael sur la nécessité de
remplacer « / » par « @ » quand il n'y a pas de « / » dans l'expression.
D'autant plus que pour d'autres types de contrôles il pourrait très bien
y avoir un « @ » (pour une adresse de courriel par exemple).

Avatar
Olivier Berquin
Vous avez raison. Je ne suis pas assez rigoureux.
Merci aussi de penser à ma santé mentale ;-)

Je vais donc réviser tout ça!

Merci de mettre le doigt sur ces faiblesses (mes faiblesses).

Oli.
Avatar
Mickael Wolff

En revanche, je ne suis pas d'accord avec Mickael sur la nécessité de
remplacer « / » par « @ » quand il n'y a pas de « / » dans l'expression.
D'autant plus que pour d'autres types de contrôles il pourrait très bien
y avoir un « @ » (pour une adresse de courriel par exemple).


Certes, en pratique je n'utilises jamais arobase. Je lui préfère
l'antiquote « ` ». Mais @ est plus lisible pour l'exemple :) Et puis
c'est une question de goût, de cohérence, et de praticité. C'était juste
pour dire d'éviter le slash, car ça donne rapidement des expressions
indigestes.

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org

Avatar
Olivier Miakinen

En revanche, je ne suis pas d'accord avec Mickael sur la nécessité de
remplacer « / » par « @ » quand il n'y a pas de « / » dans l'expression.
D'autant plus que pour d'autres types de contrôles il pourrait très bien
y avoir un « @ » (pour une adresse de courriel par exemple).


Certes, en pratique je n'utilises jamais arobase.


;-)

[...] C'était juste pour dire d'éviter le slash, car ça donne rapidement
des expressions indigestes.


Eh bien je ne suis *vraiment* pas d'accord avec ça.

Personnellement j'utilise toujours le slash quand il n'y a pas de slash
dans l'expression, car c'est le caractère le plus fréquemment employé à
cet usage, par exemple dans sed, vi ou JavaScript, et c'est pour cette
raison le plus lisible.

Bien sûr, quand il y a ne serait-ce qu'un slash dans l'expression, alors
je n'utilise jamais le slash comme délimiteur, et je choisis parmi la
centaine de caractères autorisés¹ celui qui me paraît le plus pertinent.
Cela peut-être '|' ou '`' s'ils ne sont pas utilisés, mais cela pourrait
tout aussi bien être ':' ou '='. Par ailleurs, je ne l'ai encore jamais
fait, mais je pourrais bien utiliser l'une des paires (), {}, [], et <>,
autorisées depuis PHP 4.0.4.

En fait, je trouve formidable que, alors que la syntaxe nous offre une
immense liberté de choix pour éviter les caractères d'échappement, on
puisse vouloir restreindre cette liberté en déconseillant l'utilisation
d'un délimiteur donné, et en particulier celui qui est utilisé de la
façon la plus universelle !

D'où mon coup de gueule. Note que mon opinion à ce sujet n'est guère
différente de celle concernant l'utilisation des guillemets doubles pour
les chaînes PHP, les variables à l'intérieur, et les guillemets simples
pour les attributs HTML².


Cordialement néanmoins,
--
Olivier Miakinen

(¹) Je me limite malgré tout au répertoire us-ascii pour éviter des
problèmes entre Latin1 et UTF-8 par exemple.

(²) Exemple :
"<a href='$url'>" contre "<a href="$url">" ou '<a href="'.$url.'">'


Avatar
Olivier Miakinen
Le 25/02/2008 16:55, je répondais à Mickael Wolff :

[...] je choisis parmi la centaine de caractères autorisés¹ celui qui
me paraît le plus pertinent.
[...]
(¹) Je me limite malgré tout au répertoire us-ascii pour éviter des
problèmes entre Latin1 et UTF-8 par exemple.


Vérification faite, il n'y a pas une centaine de caractères autorisés
quand on s'interdit autre chose que us-ascii, mais une trentaine tout
au plus. J'avais cru naïvement que les caractères alphanumériques en
faisaient partie, même s'il ne me serait pas venu à l'idée de choisir
l'un d'entre eux comme délimiteur. Quoi qu'il en soit, ça ne change
rien à mon opinion (et à mon coup de gueule).

Avatar
Olivier Berquin
Voici ma fonction:
function my_is_numeric($valeur)
{
$is_num = preg_match('/^[+-]?[0-9]*[,.]*[0-9]*$/', $valeur);
return ($is_num);
}


Et voici un petit tableau avec quelques exemples de valeurs acceptées
ou refusées (en rouge):
<http://olivier.berquin.free.fr/job/test_montant>

Auriez-vous la gentillesse de me dire si c'est assez rigoureux sans
être trop rigide?

Merci pour tous vos précieux conseils...

Oli.
Avatar
P'tit Marcel
[...] C'était juste pour dire d'éviter le slash, car ça donne rapidement
des expressions indigestes.


Eh bien je ne suis *vraiment* pas d'accord avec ça.

Personnellement j'utilise toujours le slash quand il n'y a pas de slash
dans l'expression, car c'est le caractère le plus fréquemment employé à
cet usage, par exemple dans sed, vi ou JavaScript, et c'est pour cette
raison le plus lisible.


Hé bien je ne suis *vraiment* pas d'accord avec ton *vrai* désaccord ;-)

Un masque est déjà assez difficile à lire, autant ne pas le borner par
des caractères imposants par la taille et qui cachent l'essentiel, à
savoir les classes de caractères [], les sous-masques () et autres
assertions ?< ?=. Par ailleurs, on parle d'un délimiteur et les
délimiteurs de loin les plus fréquents en programmation sont les
guillemets simples ou doubles. L'antiguillemet simple ` est une
approximation proche de ces délimiteurs habituels. La preuve que c'est
un bon choix, c'est que c'est le caractère que j'utilise dans les
masques preg_*** !

Le vrai scandale est qu'il soit nécessaire d'employer un délimiteur. Le
premier paramètre des fonctions preg_** correspond en réalité à deux
propriétés qui n'ont rien à voir entre elles: d'une part le masque et
d'autre part les modificateurs. Dans tout langage digne de ce nom, ces
propriétés seraient transmises dans deux paramètres distincts.

c'étaient mes deux yuans.

a+
--
P'tit Marcel
stats sur les forums modérés http://www.centrale-lyon.org/ng/


Avatar
P'tit Marcel
$is_num = preg_match('/^[+-]?[0-9]*[,.]*[0-9]*$/', $valeur);


Mes remarques à 2 roupies :
- il est inutile d'échapper le point dans une classe donc [,.]
- contrairement aux premières versions, ce masque ne permet pas de
séparateurs de milliers (sauf pour les nombres entiers inférieurs à un
million)

a+
--
P'tit Marcel
stats sur les forums modérés http://www.centrale-lyon.org/ng/

1 2 3 4