Vous pouvez également utiliser StringUtils.isNumericSpacece qui renvoie truepour les chaînes vides et ignore les espaces internes dans la chaîne. Une autre façon consiste à utiliser NumberUtils.isParsablequi vérifie fondamentalement que le nombre est analysable selon Java. (Les javadocs liés contiennent des exemples détaillés pour chaque méthode.)
StringUtils.isNumeric()ne serait probablement pas approprié ici car il vérifie uniquement si la chaîne est une séquence de chiffres. Ce serait bien pour la plupart des entiers, mais pas pour les nombres avec décimales, séparateurs de groupe, etc.
Jeff Mercado
42
réinventer la roue parce que vous n'incluez pas une bibliothèque entière parce que vous avez besoin d'une fonction de 3 lignes au même endroit.
dalvarezmartinez1
12
Cela vaut-il vraiment la peine d'ajouter une bibliothèque entière pour cette fonctionnalité? Évidemment, s'il est utilisé avec d'autres choses, c'est génial, mais c'est probablement exagéré étant donné que les gens ont résolu cela en une seule ligne de code.
Water
7
Ne fonctionne pas avec les négatifs. Et la moitié de tous les nombres sont négatifs, alors .....
Paul Draper
6
@PaulDraper: Vous avez raison, StringUtilsne prend pas en charge les principaux signes mais vous devriez vérifier NumberUtils.isCreatable, il prend correctement en charge les négatifs.
palacsint
904
Cela se fait généralement avec une simple fonction définie par l'utilisateur (c'est-à-dire la fonction Roll-your-own "isNumeric").
Cependant, si vous appelez souvent cette fonction et que vous vous attendez à ce que la plupart des vérifications échouent en raison de leur non-nombre, les performances de ce mécanisme ne seront pas excellentes, car vous comptez sur des exceptions levées pour chaque échec, ce qui est une opération assez coûteuse.
Une autre approche peut être d'utiliser une expression régulière pour vérifier la validité d'un nombre:
publicstaticboolean isNumeric(String str){return str.matches("-?\\d+(\\.\\d+)?");//match a number with optional '-' and decimal.}
Soyez prudent avec le mécanisme RegEx ci-dessus, car il échouera si vous utilisez des chiffres non arabes (c'est-à-dire des chiffres autres que 0 à 9). Cela est dû au fait que la partie "\ d" du RegEx ne correspondra qu'à [0-9] et n'est en fait pas au niveau international. (Merci à OregonGhost de l'avoir signalé!)
Ou même une autre alternative consiste à utiliser l'objet java.text.NumberFormat intégré de Java pour voir si, après l'analyse de la chaîne, la position de l'analyseur se trouve à la fin de la chaîne. Si c'est le cas, nous pouvons supposer que la chaîne entière est numérique:
\ D dans Java Regex ne correspond-il qu'aux chiffres latins? Si c'est comme des expressions régulières .NET, vous rencontrerez un problème avec d'autres chiffres (par exemple arabes), comme expliqué ici: blogs.msdn.com/oldnewthing/archive/2004/03/09/86555.aspx
OregonGhost
3
la solution numberFormatter n'est probablement que légèrement meilleure que la capture de NumberFormatException. Je soupçonne que la meilleure façon est d'utiliser une expression régulière.
Chii
11
Notez que .dans votre regex correspondra à n'importe quel caractère, pas seulement le caractère séparateur décimal.
jqno
9
+1 pour réaliser les frais d'essais / captures. C'est en fait une approche horrible à utiliser à long terme pour une utilisation répétée, mais nous sommes vraiment coincés avec cela en Java.
demongolem
5
Notez qu'il n'y a pas de "chiffres latins", et les chiffres 0-9 sont en fait des chiffres arabes. Les gens connaissent probablement les chiffres romains, qui étaient utilisés par les personnes qui parlaient latin, sous la forme I, II, III, IV, V, VI, etc. en.wikipedia.org/wiki/Arabic_numerals ; en.wikipedia.org/wiki/Roman_numerals
@ kape123 :) sûr que "123.456" ne contient pas de chiffres.
Ahmed Alejo
8
Remarque: cela se traduit par NPE pour une entrée nulle. De plus, ne fonctionne pas avec des nombres négatifs ou décimaux.
gMale
2
Je l'aime!! Je pense que c'est absolument pour les chiffres. Pas pour .,-
illusionJJ
C'est exactement ce que je cherchais. Quelque chose de simple à vérifier pour les seuls chiffres 0-9. J'ai mis un filtre dans la déclaration de mon EditText mais juste au cas où cela serait changé ou remplacé en cours de route, il est agréable d'avoir également une vérification programmatique simple.
Vous pouvez également utiliser une référence de méthode: someString.chars (). AllMatch (Character :: isDigit)
Wienczny
3
Sympa mais ça réinvente la roue comme presque toutes les "solutions" ici. Échoue également sur 'null' (comme presque tous les autres).
qben
8
Cette réponse est concise, simple et lisible. Vous pouvez presque le lire comme l'anglais - "les caractères correspondent à tous les chiffres". Il ne nécessite aucune bibliothèque tierce. Il n'utilise pas d'exceptions dans des cas non exceptionnels. Cela devrait devenir la réponse acceptée.
Andy Thomas
14
Que produira-t-il pour "-1"?
Balázs Németh
2
Pas la bonne réponse. Une chaîne numérique peut avoir des caractères non numériques (ex. "." Ou "-") tout en étant parfaitement numérique. Par exemple, 0,5, -1 et 1 000 échoueront tous avec cette réponse et pourtant ils sont parfaitement numériques.
Simeon G
126
Comme @CraigTP l'avait mentionné dans son excellente réponse, j'ai également des problèmes de performances similaires concernant l'utilisation d'exceptions pour tester si la chaîne est numérique ou non. Je finis donc par diviser la chaîne et l'utiliser java.lang.Character.isDigit().
publicstaticboolean isNumeric(String str){for(char c : str.toCharArray()){if(!Character.isDigit(c))returnfalse;}returntrue;}
Selon le Javadoc ,Character.isDigit(char) reconnaîtra correctement les chiffres non latins. En termes de performances, je pense qu'un simple nombre N de comparaisons où N est le nombre de caractères dans la chaîne serait plus efficace en termes de calcul que de faire une correspondance regex.
MISE À JOUR: Comme l'a souligné Jean-François Corbett dans le commentaire, le code ci-dessus ne validerait que les entiers positifs, ce qui couvre la majorité de mon cas d'utilisation. Vous trouverez ci-dessous le code mis à jour qui valide correctement les nombres décimaux en fonction des paramètres régionaux par défaut utilisés dans votre système, en supposant que le séparateur décimal ne se produit qu'une seule fois dans la chaîne.
publicstaticboolean isStringNumeric(String str ){DecimalFormatSymbols currentLocaleSymbols =DecimalFormatSymbols.getInstance();char localeMinusSign = currentLocaleSymbols.getMinusSign();if(!Character.isDigit( str.charAt(0))&& str.charAt(0)!= localeMinusSign )returnfalse;boolean isDecimalSeparatorFound =false;char localeDecimalSeparator = currentLocaleSymbols.getDecimalSeparator();for(char c : str.substring(1).toCharArray()){if(!Character.isDigit( c )){if( c == localeDecimalSeparator &&!isDecimalSeparatorFound ){
isDecimalSeparatorFound =true;continue;}returnfalse;}}returntrue;}
Le séparateur décimal ne provoquera-t-il pas également cet échec?
Jean-François Corbett
1
@ Jean-FrançoisCorbett: Bon point, j'ai mis à jour le code avec un nouveau qui accepte les séparateurs décimaux.
Ibrahim Arief
2
Le signe -ve échoue-t-il à cette fonction?
java_mouse
3
L'appel toCharArray()créera une copie du tableau dans l'objet String car les chaînes sont immuables. Probablement plus rapide pour utiliser charAt(int index)directement la méthode sur l'objet String.
Mike Kucera
2
Générera une StringIndexOutOfBoundsExceptionfois passé une chaîne de longueur 0. Peut être corrigé avecif(str.length() == 0) return false;
samgak
43
La bibliothèque goyave de Google fournit une méthode d'aide agréable de le faire: Ints.tryParse. Vous l'utilisez comme Integer.parseIntmais il renvoie nullplutôt que de lever une exception si la chaîne n'analyse pas un entier valide. Notez qu'il renvoie Integer, pas int, vous devez donc le reconvertir / mettre en boîte automatique en int.
Cependant, depuis la version actuelle - Guava r11 - il est toujours marqué @Beta.
Je ne l'ai pas comparé. En regardant le code source, il y a des frais généraux provenant de beaucoup de vérifications d'intégrité, mais à la fin ils utilisent Character.digit(string.charAt(idx)), similaire, mais légèrement différent de, la réponse de @Ibrahim ci-dessus. Il n'y a aucune exception pour gérer les frais généraux sous les couvertures dans leur mise en œuvre.
La réponse acceptée, trois ans plus tôt, était déjà couverte Number.isNumber().
Andy Thomas
Je ne pense pas. Il a été mis à jour ou a changé la réponse acceptée. Je me souviens que la réponse acceptée ne couvrait pas NumberUtils, c'est pourquoi j'ai ajouté ma réponse. Mais merci pour le commentaire
Goot
2
@Goot - L'historique de la réponse acceptée montre qu'elle Number.isNumber()était présente à partir de la première version de la réponse, datée du 24 septembre 12 à 17h01.
Andy Thomas
@Goot, c'est assez bon car il couvre également la vérification de la valeur décimale, contrairement à StringUtils.
Heena Hussain
24
Pourquoi tout le monde fait pression pour des solutions d'exception / regex?
Bien que je puisse comprendre que la plupart des gens utilisent bien try / catch, si vous voulez le faire fréquemment ... cela peut être extrêmement éprouvant.
Ce que j'ai fait ici a été de prendre l'expression rationnelle, les méthodes parseNumber () et la méthode de recherche de tableau pour voir laquelle était la plus efficace. Cette fois, je n'ai regardé que des nombres entiers.
publicstaticboolean isNumericRegex(String str){if(str ==null)returnfalse;return str.matches("-?\\d+");}publicstaticboolean isNumericArray(String str){if(str ==null)returnfalse;char[] data = str.toCharArray();if(data.length <=0)returnfalse;int index =0;if(data[0]=='-'&& data.length >1)
index =1;for(; index < data.length; index++){if(data[index]<'0'|| data[index]>'9')// Character.isDigit() can go here too.returnfalse;}returntrue;}publicstaticboolean isNumericException(String str){if(str ==null)returnfalse;try{/* int i = */Integer.parseInt(str);}catch(NumberFormatException nfe){returnfalse;}returntrue;}
Les résultats en vitesse que j'ai obtenus étaient:
Done with:for(int i =0; i <10000000; i++)...With only valid numbers ("59815833" and "-59815833"):Array numeric took 395.808192 ms [39.5808192 ns each]Regex took 2609.262595 ms [260.9262595 ns each]Exception numeric took 428.050207 ms [42.8050207 ns each]// Negative signArray numeric took 355.788273 ms [35.5788273 ns each]Regex took 2746.278466 ms [274.6278466 ns each]Exception numeric took 518.989902 ms [51.8989902 ns each]// Single value ("1")Array numeric took 317.861267 ms [31.7861267 ns each]Regex took 2505.313201 ms [250.5313201 ns each]Exception numeric took 239.956955 ms [23.9956955 ns each]// With Character.isDigit()Array numeric took 400.734616 ms [40.0734616 ns each]Regex took 2663.052417 ms [266.3052417 ns each]Exception numeric took 401.235906 ms [40.1235906 ns each]With invalid characters ("5981a5833" and "a"):Array numeric took 343.205793 ms [34.3205793 ns each]Regex took 2608.739933 ms [260.8739933 ns each]Exception numeric took 7317.201775 ms [731.7201775 ns each]// With a single character ("a")Array numeric took 291.695519 ms [29.1695519 ns each]Regex took 2287.25378 ms [228.725378 ns each]Exception numeric took 7095.969481 ms [709.5969481 ns each]Withnull:Array numeric took 214.663834 ms [21.4663834 ns each]Regex took 201.395992 ms [20.1395992 ns each]Exception numeric took 233.049327 ms [23.3049327 ns each]Exception numeric took 6603.669427 ms [660.3669427 ns each]if there is no if/null check
Avertissement: je ne prétends pas que ces méthodes sont optimisées à 100%, elles sont juste pour la démonstration des données
Des exceptions sont gagnées si et seulement si le nombre est de 4 caractères ou moins, et chaque chaîne est toujours un nombre ... dans ce cas, pourquoi même avoir un chèque?
En bref, c'est extrêmement douloureux si vous rencontrez fréquemment des nombres invalides avec le try / catch, ce qui est logique. Une règle importante que je respecte toujours est de ne JAMAIS utiliser try / catch pour le déroulement du programme . C'est un exemple pourquoi.
Fait intéressant, le simple si char <0 || > 9 était extrêmement simple à écrire, facile à retenir (et devrait fonctionner dans plusieurs langues) et remporte presque tous les scénarios de test.
Le seul inconvénient est que je suppose que Integer.parseInt () pourrait gérer les nombres non ASCII, contrairement à la méthode de recherche de tableau.
Pour ceux qui se demandent pourquoi j'ai dit qu'il est facile de se souvenir du tableau de caractères, si vous savez qu'il n'y a pas de signes négatifs, vous pouvez facilement vous en sortir avec quelque chose de condensé comme ceci:
publicstaticboolean isNumericArray(String str){if(str ==null)returnfalse;for(char c : str.toCharArray())if(c <'0'|| c >'9')returnfalse;returntrue;
Enfin, en guise de note finale, j'étais curieux de voir l'opérateur d'assignation dans l'exemple accepté avec tous les votes. Ajout de l'affectation de
double d =Double.parseDouble(...)
est non seulement inutile car vous n'utilisez même pas la valeur, mais cela gaspille du temps de traitement et augmente le temps d'exécution de quelques nanosecondes (ce qui entraîne une augmentation de 100 à 200 ms des tests). Je ne vois pas pourquoi quelqu'un ferait cela, car il s'agit en fait d'un travail supplémentaire pour réduire les performances.
On pourrait penser que ce serait optimisé ... bien que je devrais peut-être vérifier le bytecode et voir ce que fait le compilateur. Cela n'explique pas pourquoi cela s'est toujours avéré plus long pour moi, mais s'il est en quelque sorte optimisé ... je me demande donc ce qui se passe. Remarque: par plus long, je veux dire exécuter le test pour 10000000 itérations, et exécuter ce programme plusieurs fois (10x +) a toujours montré qu'il était plus lent.
EDIT: mise à jour d'un test pour Character.isDigit ()
Cela ne compile-t-il pas une nouvelle expression régulière à chaque fois? Cela ne semble pas très efficace.
Samuel Edwin Ward
1
@SamuelEdwinWard Cest la toute raison que je fait ce post ... l'exemple utilisé les réponses regex fournies d'autres personnes et a montré comment il est inefficace. Même si vous essayez de regex en le pré-compilant à l'avance et en n'utilisant que cela, les différences de temps sont: 2587 ms pour le regex que j'ai posté d'autres personnes fournies, 950 ms lorsqu'il est compilé à l'avance, 144 ms lorsque vous le faites en tant que tableau numérique (pour 1 mil itérations de la même chaîne). Compiler à l'avance aiderait évidemment, mais malheureusement c'est toujours assez inférieur à la manière de la matrice ... à moins qu'il y ait une optimisation folle que je ne connais pas.
Water
Croire que Regex accélère les choses est presque une erreur. Si c'est une recherche ponctuelle, oui, je comprends ... mais j'ai remarqué qu'un code écrit efficacement surpasse en fait suffisamment l'expression régulière pour vous choquer! Great post @Water
L'expression régulière de CraigTP (illustrée ci-dessus) produit des faux positifs. Par exemple, "23y4" sera compté comme un nombre car "." correspond à n'importe quel caractère et non à la virgule décimale.
De plus, il rejettera tout numéro avec un «+» en tête
Une alternative qui évite ces deux problèmes mineurs est
cela reviendra truepour un seul plus "+"ou moins "-", et falsepour"0."
user85421
Bonne prise sur le simple plus ou moins. Est "0". un numéro valide?
user872985
"0."est valable pour Double.parseDouble()et est un littéral valide selon le JLS ( §3.10.2 )!
user85421
La création d'expressions régulières est également coûteuse. L'expression régulière doit être créée une fois et réutilisée
Daniel Nouriev
1
vous devriez le changer enmatches("-?\\d+([.]\\d+)?")
Bobs
14
Nous pouvons essayer de remplacer tous les nombres de la chaîne donnée par ("") c'est-à-dire un espace vide et si après cela la longueur de la chaîne est nulle, alors nous pouvons dire que la chaîne donnée ne contient que des nombres. [Si vous avez trouvé cette réponse utile, pensez à la voter] Exemple:
boolean isNumber(String str){if(str.length()==0)returnfalse;//To check if string is emptyif(str.charAt(0)=='-')
str = str.replaceFirst("-","");// for handling -ve numbersSystem.out.println(str);
str = str.replaceFirst("\\.","");//to check if it contains more than one decimal pointsif(str.length()==0)returnfalse;// to check if it is empty string after removing -ve sign and decimal pointSystem.out.println(str);return str.replaceAll("[0-9]","").length()==0;}
Donc , ""est un nombre , mais "3.14"et "-1"ne sont pas?
Eric Duminil
Évidemment, cela ne s'applique pas à toutes les formes de nombres, mais voici une note positive pour penser différemment ... si la pensée originale était la vôtre, c'est-à-dire.
Un fourre - tout méthode de commodité que vous pouvez utiliser pour analyser une chaîne avec tout type d'analyseur: isParsable(Object parser, String str). L'analyseur peut être un Classou un object. Cela vous permettra également d'utiliser des analyseurs personnalisés que vous avez écrits et devrait fonctionner pour tous les scénarios, par exemple:
isParsable(Integer.class,"11");
isParsable(Double.class,"11.11");Object dateFormater =new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
isParsable(dateFormater,"2001.07.04 AD at 12:08:56 PDT");
Voici mon code complet avec des descriptions de méthode.
import java.lang.reflect.*;/**
* METHOD: isParsable<p><p>
*
* This method will look through the methods of the specified <code>from</code> parameter
* looking for a public method name starting with "parse" which has only one String
* parameter.<p>
*
* The <code>parser</code> parameter can be a class or an instantiated object, eg:
* <code>Integer.class</code> or <code>new Integer(1)</code>. If you use a
* <code>Class</code> type then only static methods are considered.<p>
*
* When looping through potential methods, it first looks at the <code>Class</code> associated
* with the <code>parser</code> parameter, then looks through the methods of the parent's class
* followed by subsequent ancestors, using the first method that matches the criteria specified
* above.<p>
*
* This method will hide any normal parse exceptions, but throws any exceptions due to
* programmatic errors, eg: NullPointerExceptions, etc. If you specify a <code>parser</code>
* parameter which has no matching parse methods, a NoSuchMethodException will be thrown
* embedded within a RuntimeException.<p><p>
*
* Example:<br>
* <code>isParsable(Boolean.class, "true");<br>
* isParsable(Integer.class, "11");<br>
* isParsable(Double.class, "11.11");<br>
* Object dateFormater = new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");<br>
* isParsable(dateFormater, "2001.07.04 AD at 12:08:56 PDT");<br></code>
* <p>
*
* @param parser The Class type or instantiated Object to find a parse method in.
* @param str The String you want to parse
*
* @return true if a parse method was found and completed without exception
* @throws java.lang.NoSuchMethodException If no such method is accessible
*/publicstaticboolean isParsable(Object parser,String str){Class theClass =(parser instanceofClass?(Class)parser: parser.getClass());boolean staticOnly =(parser == theClass), foundAtLeastOne =false;Method[] methods = theClass.getMethods();// Loop over methodsfor(int index =0; index < methods.length; index++){Method method = methods[index];// If method starts with parse, is public and has one String parameter.// If the parser parameter was a Class, then also ensure the method is static. if(method.getName().startsWith("parse")&&(!staticOnly ||Modifier.isStatic(method.getModifiers()))&&Modifier.isPublic(method.getModifiers())&&
method.getGenericParameterTypes().length ==1&&
method.getGenericParameterTypes()[0]==String.class){try{
foundAtLeastOne =true;
method.invoke(parser, str);returntrue;// Successfully parsed without exception}catch(Exception exception){// If invoke problem, try a different method/*if(!(exception instanceof IllegalArgumentException) &&
!(exception instanceof IllegalAccessException) &&
!(exception instanceof InvocationTargetException))
continue; // Look for other parse methods*/// Parse method refuses to parse, look for another different methodcontinue;// Look for other parse methods}}}// No more accessible parse method could be found.if(foundAtLeastOne)returnfalse;elsethrownewRuntimeException(newNoSuchMethodException());}/**
* METHOD: willParse<p><p>
*
* A convienence method which calls the isParseable method, but does not throw any exceptions
* which could be thrown through programatic errors.<p>
*
* Use of {@link #isParseable(Object, String) isParseable} is recommended for use so programatic
* errors can be caught in development, unless the value of the <code>parser</code> parameter is
* unpredictable, or normal programtic exceptions should be ignored.<p>
*
* See {@link #isParseable(Object, String) isParseable} for full description of method
* usability.<p>
*
* @param parser The Class type or instantiated Object to find a parse method in.
* @param str The String you want to parse
*
* @return true if a parse method was found and completed without exception
* @see #isParseable(Object, String) for full description of method usability
*/publicstaticboolean willParse(Object parser,String str){try{return isParsable(parser, str);}catch(Throwable exception){returnfalse;}}
Une approche performante évitant les tentatives de capture et la manipulation des nombres négatifs et de la notation scientifique.
Pattern PATTERN =Pattern.compile("^(-?0|-?[1-9]\\d*)(\\.\\d+)?(E\\d+)?$");publicstaticboolean isNumeric(String value ){return value !=null&& PATTERN.matcher( value ).matches();}
Voici ma classe pour vérifier si une chaîne est numérique. Il corrige également les chaînes numériques:
Fonctionnalités:
Supprime les zéros inutiles ["12.0000000" -> "12"]
Supprime les zéros inutiles ["12.0580000" -> "12.058"]
Supprime les caractères non numériques ["12.00sdfsdf00" -> "12"]
Gère les valeurs de chaîne négatives ["-12,020000" -> "-12.02"]
Supprime plusieurs points ["-12.0.20.000" -> "-12.02"]
Pas de bibliothèques supplémentaires, juste Java standard
Voici...
publicclassNumUtils{/**
* Transforms a string to an integer. If no numerical chars returns a String "0".
*
* @param str
* @return retStr
*/staticString makeToInteger(String str){String s = str;double d;
d =Double.parseDouble(makeToDouble(s));int i =(int)(d +0.5D);String retStr =String.valueOf(i);System.out.printf(retStr +" ");return retStr;}/**
* Transforms a string to an double. If no numerical chars returns a String "0".
*
* @param str
* @return retStr
*/staticString makeToDouble(String str){Boolean dotWasFound =false;String orgStr = str;String retStr;int firstDotPos =0;Boolean negative =false;//check if str is nullif(str.length()==0){
str="0";}//check if first sign is "-"if(str.charAt(0)=='-'){
negative =true;}//check if str containg any number or else set the string to '0'if(!str.matches(".*\\d+.*")){
str ="0";}//Replace ',' with '.' (for some european users who use the ',' as decimal separator)
str = str.replaceAll(",",".");
str = str.replaceAll("[^\\d.]","");//Removes the any second dotsfor(int i_char =0; i_char < str.length(); i_char++){if(str.charAt(i_char)=='.'){
dotWasFound =true;
firstDotPos = i_char;break;}}if(dotWasFound){String befDot = str.substring(0, firstDotPos +1);String aftDot = str.substring(firstDotPos +1, str.length());
aftDot = aftDot.replaceAll("\\.","");
str = befDot + aftDot;}//Removes zeros from the beginingdouble uglyMethod =Double.parseDouble(str);
str =String.valueOf(uglyMethod);//Removes the .0
str = str.replaceAll("([0-9])\\.0+([^0-9]|$)","$1$2");
retStr = str;if(negative){
retStr ="-"+retStr;}return retStr;}staticboolean isNumeric(String str){try{double d =Double.parseDouble(str);}catch(NumberFormatException nfe){returnfalse;}returntrue;}}
Les exceptions sont coûteuses, mais dans ce cas, le RegEx prend beaucoup plus de temps. Le code ci-dessous montre un test simple de deux fonctions - une utilisant des exceptions et une utilisant des expressions régulières. Sur ma machine, la version RegEx est 10 fois plus lente que l'exception.
import java.util.Date;publicclassIsNumeric{publicstaticboolean isNumericOne(String s){return s.matches("-?\\d+(\\.\\d+)?");//match a number with optional '-' and decimal. }publicstaticboolean isNumericTwo(String s){try{Double.parseDouble(s);returntrue;}catch(Exception e){returnfalse;}}publicstaticvoid main(String[] args){String test ="12345.F";long before =newDate().getTime();for(int x=0;x<1000000;++x){//isNumericTwo(test);
isNumericOne(test);}long after =newDate().getTime();System.out.println(after-before);}}
En général, je pense que ce type de code serait utilisé pour vérifier des choses comme la saisie dactylographiée. Dans ce cas, la vitesse n'est pas une considération et faire quelque chose d'aussi laid que de lever une exception pour vérifier le nombre ou le non-nombre est mauvais.
user872985
Peut être pas. L'entrée typée est généralement vérifiée par le composant UI où les erreurs peuvent être immédiatement affichées avant de soumettre la valeur. Il peut être plus courant de valider des chaînes à partir de gros fichiers texte d'entrée - là où les performances sont importantes. Le but de ma réponse ici est de répondre à l'énoncé «les exceptions sont lentes» dans la réponse acceptée. Les regex complexes sont beaucoup plus chers. Et il n'y a pas de "vilain lancer" dans mon code - juste un moyen plus rapide de détecter les violations. Avec une approche de vérification d'abord puis de calcul, vous effectuez deux passages à travers l'entrée: un pour vérifier et un autre pour convertir.
ChrisCantrell
5
// veuillez vérifier le code ci-dessous
publicstaticboolean isDigitsOnly(CharSequence str){finalint len = str.length();for(int i =0; i < len; i++){if(!Character.isDigit(str.charAt(i))){returnfalse;}}returntrue;}
La question dit "numérique" qui pourrait inclure des valeurs non entières.
rghome
3
// only intpublicstaticboolean isNumber(int num){return(num >=48&& c <=57);// 0 - 9}// is type of number including . - e E publicstaticboolean isNumber(String s){boolean isNumber =true;for(int i =0; i < s.length()&& isNumber; i++){char c = s.charAt(i);
isNumber = isNumber &((c >='0'&& c <='9')||(c =='.')||(c =='e')||(c =='E')||(c ==''));}return isInteger;}// is type of number publicstaticboolean isInteger(String s){boolean isInteger =true;for(int i =0; i < s.length()&& isInteger; i++){char c = s.charAt(i);
isInteger = isInteger &((c >='0'&& c <='9'));}return isInteger;}publicstaticboolean isNumeric(String s){try{Double.parseDouble(s);returntrue;}catch(Exception e){returnfalse;}}
publicstaticboolean isNumericString(String input){boolean result =false;if(input !=null&& input.length()>0){char[] charArray = input.toCharArray();for(char c : charArray){if(c >='0'&& c <='9'){// it is a digit
result =true;}else{
result =false;break;}}}return result;}
J'ai modifié la solution de CraigTP pour accepter la notation scientifique ainsi que les points et les virgules comme séparateurs décimaux
^-?\d+([,\.]\d+)?([eE]-?\d+)?$
exemple
var re =newRegExp("^-?\d+([,\.]\d+)?([eE]-?\d+)?$");
re.test("-6546");// true
re.test("-6546355e-4456");// true
re.test("-6546.355e-4456");// true, though debatable
re.test("-6546.35.5e-4456");// false
re.test("-6546.35.5e-4456.6");// false
C'est pourquoi j'aime l'approche Try * dans .NET. En plus de la méthode Parse traditionnelle similaire à celle de Java, vous disposez également d'une méthode TryParse. Je ne suis pas bon en syntaxe Java (hors paramètres?), Veuillez donc traiter ce qui suit comme une sorte de pseudo-code. Cela devrait cependant clarifier le concept.
boolean parseInteger(String s, out int number){try{
number =Integer.parseInt(myString);returntrue;}catch(NumberFormatException e){returnfalse;}}
Usage:
int num;if(parseInteger("23", out num)){// Do something with num.}
oui, il n'y a pas de "paramètres de sortie" en Java et comme le wrapper Integer est immuable (ne peut donc pas être utilisé comme référence valide pour stocker la sortie), l'option idiomatique raisonnable serait de renvoyer un objet Integer qui pourrait être nul si l'analyse échoué. Une option plus laide pourrait être de passer un int [1] comme paramètre de sortie.
fortran
Oui, je me souviens d'une discussion sur pourquoi Java n'a pas de paramètres de sortie. mais renvoyer un entier (comme nul, si nécessaire) serait bien aussi, je suppose, bien que je ne connaisse pas les performances de Java en ce qui concerne la boxe / unboxing.
OregonGhost
4
J'aime C # autant que le prochain, mais il est inutile d'ajouter un extrait de code .NET C # pour une question Java lorsque les fonctionnalités n'existent pas en Java
Shane
Cela créerait un problème de sonar si vous ne connectez pas l'exception
jmhostalet
2
Analysez-le (c'est-à-dire avec Integer#parseInt) et attrapez simplement l'exception. =)
Pour clarifier: La fonction parseInt vérifie si elle peut analyser le nombre dans tous les cas (évidemment) et si vous souhaitez l'analyser de toute façon, vous n'allez pas affecter les performances en effectuant l'analyse.
Si vous ne souhaitez pas l'analyser (ou l'analyser très, très rarement), vous pouvez bien sûr le faire différemment.
J'ai illustré certaines conditions pour vérifier les nombres et les décimales sans utiliser d'API,
Vérifier la longueur fixe Numéro à 1 chiffre
Character.isDigit(char)
Vérifiez le numéro de longueur fixe (en supposant que la longueur est de 6)
String number ="132452";if(number.matches("([0-9]{6})"))System.out.println("6 digits number identified");
Vérifiez le numéro de longueur variable entre (supposez une longueur de 4 à 6)
// {n,m} n <= length <= mString number ="132452";if(number.matches("([0-9]{4,6})"))System.out.println("Number Identified between 4 to 6 length");String number ="132";if(!number.matches("([0-9]{4,6})"))System.out.println("Number not in length range or different format");
Vérifier le nombre décimal de longueur variable entre (supposer une longueur de 4 à 7)
// It will not count the '.' (Period) in lengthString decimal ="132.45";if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))System.out.println("Numbers Identified between 4 to 7");String decimal ="1.12";if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))System.out.println("Numbers Identified between 4 to 7");String decimal ="1234";if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))System.out.println("Numbers Identified between 4 to 7");String decimal ="-10.123";if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))System.out.println("Numbers Identified between 4 to 7");String decimal ="123..4";if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))System.out.println("Decimal not in range or different format");String decimal ="132";if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))System.out.println("Decimal not in range or different format");String decimal ="1.1";if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))System.out.println("Decimal not in range or different format");
Sur la base d'autres réponses, j'ai écrit la mienne et elle n'utilise pas de modèles ou d'analyse avec vérification des exceptions.
Il vérifie au maximum un signe moins et vérifie au maximum un point décimal.
Voici quelques exemples et leurs résultats:
"1", "-1", "-1.5" et "-1.556" renvoient true
"1..5", "1A.5", "1.5D", "-" et "--1" renvoient false
Remarque: Si nécessaire, vous pouvez le modifier pour accepter un paramètre de paramètres régionaux et le transmettre aux appels DecimalFormatSymbols.getInstance () pour utiliser un paramètre régional spécifique au lieu du paramètre actuel.
publicstaticboolean isNumeric(finalString input){//Check for null or blank stringif(input ==null|| input.isBlank())returnfalse;//Retrieve the minus sign and decimal separator characters from the current Localefinal var localeMinusSign =DecimalFormatSymbols.getInstance().getMinusSign();final var localeDecimalSeparator =DecimalFormatSymbols.getInstance().getDecimalSeparator();//Check if first character is a minus signfinal var isNegative = input.charAt(0)== localeMinusSign;//Check if string is not just a minus signif(isNegative && input.length()==1)returnfalse;
var isDecimalSeparatorFound =false;//If the string has a minus sign ignore the first characterfinal var startCharIndex = isNegative ?1:0;//Check if each character is a number or a decimal separator//and make sure string only has a maximum of one decimal separatorfor(var i = startCharIndex; i < input.length(); i++){if(!Character.isDigit(input.charAt(i))){if(input.charAt(i)== localeDecimalSeparator &&!isDecimalSeparatorFound){
isDecimalSeparatorFound =true;}elsereturnfalse;}}returntrue;}
Voici deux méthodes qui pourraient fonctionner. (Sans utiliser d'exceptions). Remarque: Java est une valeur de passage par défaut et la valeur d'une chaîne est l'adresse des données d'objet de la chaîne. Donc, quand vous faites
stringNumber = stringNumber.replaceAll(" ","");
Vous avez modifié la valeur d'entrée pour n'avoir aucun espace. Vous pouvez supprimer cette ligne si vous le souhaitez.
Voici une autre méthode au cas où vous souhaiteriez autoriser les flottants. Cette méthode autoriserait les nombres du formulaire à passer 1 123 123 123 123 123 123 123 Je viens de le faire et je pense qu'il a besoin de tests supplémentaires pour s'assurer qu'il fonctionne.
privateboolean isValidStringTrueNumber(String stringNumber){if(stringNumber.isEmpty()){returnfalse;}
stringNumber = stringNumber.replaceAll(" ","");int countOfDecimalPoint =0;boolean decimalPointPassed =false;boolean commaFound =false;int countOfDigitsBeforeDecimalPoint =0;int countOfDigitsAfterDecimalPoint =0;int commaCounter=0;int countOfDigitsBeforeFirstComma =0;char[] charNumber = stringNumber.toCharArray();for(int i =0; i<charNumber.length ;i++){if((commaCounter>3)||(commaCounter<0)){returnfalse;}if(!Character.isDigit(charNumber[i]))//Char is not a digit.{if(charNumber[i]==','){if(decimalPointPassed){returnfalse;}
commaFound =true;//check that next three chars are only digits.
commaCounter +=3;}elseif(charNumber[i]=='.'){
decimalPointPassed =true;
countOfDecimalPoint++;}else{returnfalse;}}else//Char is a digit.{if((commaCounter>=0)&&(commaFound)){if(!decimalPointPassed){
commaCounter--;}}if(!commaFound){
countOfDigitsBeforeFirstComma++;}if(!decimalPointPassed){
countOfDigitsBeforeDecimalPoint++;}else{
countOfDigitsAfterDecimalPoint++;}}}if((commaFound)&&(countOfDigitsBeforeFirstComma>3)){returnfalse;}if(countOfDecimalPoint>1){returnfalse;}if((decimalPointPassed)&&((countOfDigitsBeforeDecimalPoint==0)||(countOfDigitsAfterDecimalPoint==0))){returnfalse;}returntrue;}
Oh, bonne question. Je suppose que celui-ci ne fonctionne que des entiers de type normal. La méthode a été initialement créée pour filtrer les numéros de téléphone d'entrée et compter les numéros.
Integer.parseInt()
ne parviendront pas à analyser les numéros de mobile avecNumberFormatException
.Réponses:
Avec Apache Commons Lang 3.5 et supérieur:
NumberUtils.isCreatable
ouStringUtils.isNumeric
.Avec Apache Commons Lang 3.4 et versions antérieures:
NumberUtils.isNumber
ouStringUtils.isNumeric
.Vous pouvez également utiliser
StringUtils.isNumericSpace
ce qui renvoietrue
pour les chaînes vides et ignore les espaces internes dans la chaîne. Une autre façon consiste à utiliserNumberUtils.isParsable
qui vérifie fondamentalement que le nombre est analysable selon Java. (Les javadocs liés contiennent des exemples détaillés pour chaque méthode.)la source
StringUtils.isNumeric()
ne serait probablement pas approprié ici car il vérifie uniquement si la chaîne est une séquence de chiffres. Ce serait bien pour la plupart des entiers, mais pas pour les nombres avec décimales, séparateurs de groupe, etc.StringUtils
ne prend pas en charge les principaux signes mais vous devriez vérifierNumberUtils.isCreatable
, il prend correctement en charge les négatifs.Cela se fait généralement avec une simple fonction définie par l'utilisateur (c'est-à-dire la fonction Roll-your-own "isNumeric").
Quelque chose comme:
Cependant, si vous appelez souvent cette fonction et que vous vous attendez à ce que la plupart des vérifications échouent en raison de leur non-nombre, les performances de ce mécanisme ne seront pas excellentes, car vous comptez sur des exceptions levées pour chaque échec, ce qui est une opération assez coûteuse.
Une autre approche peut être d'utiliser une expression régulière pour vérifier la validité d'un nombre:
Soyez prudent avec le mécanisme RegEx ci-dessus, car il échouera si vous utilisez des chiffres non arabes (c'est-à-dire des chiffres autres que 0 à 9). Cela est dû au fait que la partie "\ d" du RegEx ne correspondra qu'à [0-9] et n'est en fait pas au niveau international. (Merci à OregonGhost de l'avoir signalé!)
Ou même une autre alternative consiste à utiliser l'objet java.text.NumberFormat intégré de Java pour voir si, après l'analyse de la chaîne, la position de l'analyseur se trouve à la fin de la chaîne. Si c'est le cas, nous pouvons supposer que la chaîne entière est numérique:
la source
.
dans votre regex correspondra à n'importe quel caractère, pas seulement le caractère séparateur décimal.si vous êtes sur android, vous devez utiliser:
la documentation peut être trouvée ici
reste simple . presque tout le monde peut "reprogrammer" (la même chose).
la source
.
,-
Expressions lambda Java 8.
la source
Comme @CraigTP l'avait mentionné dans son excellente réponse, j'ai également des problèmes de performances similaires concernant l'utilisation d'exceptions pour tester si la chaîne est numérique ou non. Je finis donc par diviser la chaîne et l'utiliser
java.lang.Character.isDigit()
.Selon le Javadoc ,
Character.isDigit(char)
reconnaîtra correctement les chiffres non latins. En termes de performances, je pense qu'un simple nombre N de comparaisons où N est le nombre de caractères dans la chaîne serait plus efficace en termes de calcul que de faire une correspondance regex.MISE À JOUR: Comme l'a souligné Jean-François Corbett dans le commentaire, le code ci-dessus ne validerait que les entiers positifs, ce qui couvre la majorité de mon cas d'utilisation. Vous trouverez ci-dessous le code mis à jour qui valide correctement les nombres décimaux en fonction des paramètres régionaux par défaut utilisés dans votre système, en supposant que le séparateur décimal ne se produit qu'une seule fois dans la chaîne.
la source
toCharArray()
créera une copie du tableau dans l'objet String car les chaînes sont immuables. Probablement plus rapide pour utilisercharAt(int index)
directement la méthode sur l'objet String.StringIndexOutOfBoundsException
fois passé une chaîne de longueur 0. Peut être corrigé avecif(str.length() == 0) return false;
La bibliothèque goyave de Google fournit une méthode d'aide agréable de le faire:
Ints.tryParse
. Vous l'utilisez commeInteger.parseInt
mais il renvoienull
plutôt que de lever une exception si la chaîne n'analyse pas un entier valide. Notez qu'il renvoie Integer, pas int, vous devez donc le reconvertir / mettre en boîte automatique en int.Exemple:
Cependant, depuis la version actuelle - Guava r11 - il est toujours marqué @Beta.
Je ne l'ai pas comparé. En regardant le code source, il y a des frais généraux provenant de beaucoup de vérifications d'intégrité, mais à la fin ils utilisent
Character.digit(string.charAt(idx))
, similaire, mais légèrement différent de, la réponse de @Ibrahim ci-dessus. Il n'y a aucune exception pour gérer les frais généraux sous les couvertures dans leur mise en œuvre.la source
N'utilisez pas d'exceptions pour valider vos valeurs. Utilisez plutôt des bibliothèques Util comme apache NumberUtils:
Modifier :
Veuillez noter que si votre chaîne commence par un 0, NumberUtils interprétera votre valeur comme hexadécimale.
la source
Number.isNumber()
.Number.isNumber()
était présente à partir de la première version de la réponse, datée du 24 septembre 12 à 17h01.Pourquoi tout le monde fait pression pour des solutions d'exception / regex?
Bien que je puisse comprendre que la plupart des gens utilisent bien try / catch, si vous voulez le faire fréquemment ... cela peut être extrêmement éprouvant.
Ce que j'ai fait ici a été de prendre l'expression rationnelle, les méthodes parseNumber () et la méthode de recherche de tableau pour voir laquelle était la plus efficace. Cette fois, je n'ai regardé que des nombres entiers.
Les résultats en vitesse que j'ai obtenus étaient:
Avertissement: je ne prétends pas que ces méthodes sont optimisées à 100%, elles sont juste pour la démonstration des données
Des exceptions sont gagnées si et seulement si le nombre est de 4 caractères ou moins, et chaque chaîne est toujours un nombre ... dans ce cas, pourquoi même avoir un chèque?
En bref, c'est extrêmement douloureux si vous rencontrez fréquemment des nombres invalides avec le try / catch, ce qui est logique. Une règle importante que je respecte toujours est de ne JAMAIS utiliser try / catch pour le déroulement du programme . C'est un exemple pourquoi.
Fait intéressant, le simple si char <0 || > 9 était extrêmement simple à écrire, facile à retenir (et devrait fonctionner dans plusieurs langues) et remporte presque tous les scénarios de test.
Le seul inconvénient est que je suppose que Integer.parseInt () pourrait gérer les nombres non ASCII, contrairement à la méthode de recherche de tableau.
Pour ceux qui se demandent pourquoi j'ai dit qu'il est facile de se souvenir du tableau de caractères, si vous savez qu'il n'y a pas de signes négatifs, vous pouvez facilement vous en sortir avec quelque chose de condensé comme ceci:
Enfin, en guise de note finale, j'étais curieux de voir l'opérateur d'assignation dans l'exemple accepté avec tous les votes. Ajout de l'affectation de
est non seulement inutile car vous n'utilisez même pas la valeur, mais cela gaspille du temps de traitement et augmente le temps d'exécution de quelques nanosecondes (ce qui entraîne une augmentation de 100 à 200 ms des tests). Je ne vois pas pourquoi quelqu'un ferait cela, car il s'agit en fait d'un travail supplémentaire pour réduire les performances.
On pourrait penser que ce serait optimisé ... bien que je devrais peut-être vérifier le bytecode et voir ce que fait le compilateur. Cela n'explique pas pourquoi cela s'est toujours avéré plus long pour moi, mais s'il est en quelque sorte optimisé ... je me demande donc ce qui se passe. Remarque: par plus long, je veux dire exécuter le test pour 10000000 itérations, et exécuter ce programme plusieurs fois (10x +) a toujours montré qu'il était plus lent.
EDIT: mise à jour d'un test pour Character.isDigit ()
la source
L'expression régulière de CraigTP (illustrée ci-dessus) produit des faux positifs. Par exemple, "23y4" sera compté comme un nombre car "." correspond à n'importe quel caractère et non à la virgule décimale.
De plus, il rejettera tout numéro avec un «+» en tête
Une alternative qui évite ces deux problèmes mineurs est
la source
true
pour un seul plus"+"
ou moins"-"
, etfalse
pour"0."
"0."
est valable pourDouble.parseDouble()
et est un littéral valide selon le JLS ( §3.10.2 )!matches("-?\\d+([.]\\d+)?")
Nous pouvons essayer de remplacer tous les nombres de la chaîne donnée par ("") c'est-à-dire un espace vide et si après cela la longueur de la chaîne est nulle, alors nous pouvons dire que la chaîne donnée ne contient que des nombres. [Si vous avez trouvé cette réponse utile, pensez à la voter] Exemple:
la source
""
est un nombre , mais"3.14"
et"-1"
ne sont pas?Vous pouvez utiliser
NumberFormat#parse
:la source
value
.Si vous utilisez Java pour développer une application Android, vous pouvez utiliser la fonction TextUtils.isDigitsOnly .
la source
Voici ma réponse au problème.
Un fourre - tout méthode de commodité que vous pouvez utiliser pour analyser une chaîne avec tout type d'analyseur:
isParsable(Object parser, String str)
. L'analyseur peut être unClass
ou unobject
. Cela vous permettra également d'utiliser des analyseurs personnalisés que vous avez écrits et devrait fonctionner pour tous les scénarios, par exemple:Voici mon code complet avec des descriptions de méthode.
la source
Pour faire correspondre uniquement les entiers de base dix positifs, qui ne contiennent que des chiffres ASCII, utilisez:
la source
Une approche performante évitant les tentatives de capture et la manipulation des nombres négatifs et de la notation scientifique.
la source
Voici ma classe pour vérifier si une chaîne est numérique. Il corrige également les chaînes numériques:
Fonctionnalités:
Voici...
la source
Voici un autre exemple de mise à niveau de l'expression régulière "CraigTP" avec plus de validations.
la source
Les exceptions sont coûteuses, mais dans ce cas, le RegEx prend beaucoup plus de temps. Le code ci-dessous montre un test simple de deux fonctions - une utilisant des exceptions et une utilisant des expressions régulières. Sur ma machine, la version RegEx est 10 fois plus lente que l'exception.
la source
// veuillez vérifier le code ci-dessous
la source
la source
Voici un exemple simple pour cette vérification:
la source
Vous pouvez utiliser l'objet java.util.Scanner.
la source
J'ai modifié la solution de CraigTP pour accepter la notation scientifique ainsi que les points et les virgules comme séparateurs décimaux
exemple
la source
C'est pourquoi j'aime l'approche Try * dans .NET. En plus de la méthode Parse traditionnelle similaire à celle de Java, vous disposez également d'une méthode TryParse. Je ne suis pas bon en syntaxe Java (hors paramètres?), Veuillez donc traiter ce qui suit comme une sorte de pseudo-code. Cela devrait cependant clarifier le concept.
Usage:
la source
Analysez-le (c'est-à-dire avec
Integer#parseInt
) et attrapez simplement l'exception. =)Pour clarifier: La fonction parseInt vérifie si elle peut analyser le nombre dans tous les cas (évidemment) et si vous souhaitez l'analyser de toute façon, vous n'allez pas affecter les performances en effectuant l'analyse.
Si vous ne souhaitez pas l'analyser (ou l'analyser très, très rarement), vous pouvez bien sûr le faire différemment.
la source
Vous pouvez utiliser NumberUtils.isCreatable () depuis Apache Commons Lang .
Étant donné que NumberUtils.isNumber sera obsolète dans 4.0, utilisez donc NumberUtils.isCreatable () à la place.
la source
Java 8 Stream, expression lambda, interface fonctionnelle
Tous les cas traités ( chaîne nulle, chaîne vide, etc. )
la source
J'ai illustré certaines conditions pour vérifier les nombres et les décimales sans utiliser d'API,
Vérifier la longueur fixe Numéro à 1 chiffre
Vérifiez le numéro de longueur fixe (en supposant que la longueur est de 6)
Vérifiez le numéro de longueur variable entre (supposez une longueur de 4 à 6)
Vérifier le nombre décimal de longueur variable entre (supposer une longueur de 4 à 7)
J'espère que cela aidera beaucoup.
la source
Sur la base d'autres réponses, j'ai écrit la mienne et elle n'utilise pas de modèles ou d'analyse avec vérification des exceptions.
Il vérifie au maximum un signe moins et vérifie au maximum un point décimal.
Voici quelques exemples et leurs résultats:
"1", "-1", "-1.5" et "-1.556" renvoient true
"1..5", "1A.5", "1.5D", "-" et "--1" renvoient false
Remarque: Si nécessaire, vous pouvez le modifier pour accepter un paramètre de paramètres régionaux et le transmettre aux appels DecimalFormatSymbols.getInstance () pour utiliser un paramètre régional spécifique au lieu du paramètre actuel.
la source
Voici deux méthodes qui pourraient fonctionner. (Sans utiliser d'exceptions). Remarque: Java est une valeur de passage par défaut et la valeur d'une chaîne est l'adresse des données d'objet de la chaîne. Donc, quand vous faites
Vous avez modifié la valeur d'entrée pour n'avoir aucun espace. Vous pouvez supprimer cette ligne si vous le souhaitez.
Voici une autre méthode au cas où vous souhaiteriez autoriser les flottants. Cette méthode autoriserait les nombres du formulaire à passer 1 123 123 123 123 123 123 123 Je viens de le faire et je pense qu'il a besoin de tests supplémentaires pour s'assurer qu'il fonctionne.
la source