Meilleure mise en œuvre pour un isNumber(string) méthode
Dans mon expérience limitée, j'ai été sur plusieurs projets qui ont eu une sorte de chaîne de l'utilitaire de classe avec des méthodes pour déterminer si une chaîne est un nombre. L'idée a toujours été le même, cependant, la mise en œuvre a été différent. Certains entourent un parse tentative avec try/catch
public boolean isInteger(String str) {
try {
Integer.parseInt(str);
return true;
} catch (NumberFormatException nfe) {}
return false;
}
et d'autres correspondent avec la regex
public boolean isInteger(String str) {
return str.matches("^-?[0-9]+(\\.[0-9]+)?$");
}
Est l'une de ces méthodes mieux que les autres? Personnellement, je préfère utiliser les regex approche, comme c'est concis, mais il va effectuer à la hauteur si elle est appelée lors de l'itération sur, disons, une liste de plusieurs centaines de milliers de chaînes?
Remarque: Comme je suis un peu nouveau sur le site je ne comprends pas tout ce Wiki de la Communauté d'affaires, donc si cela appartient-il laissez-moi savoir et je serai heureux de le déplacer.
EDIT:
Avec tous les TryParse suggestions, j'ai porté Asaph indice de référence du code (merci pour ce superbe post!) en C# et ajout d'une méthode TryParse. Et comme il semble, la TryParse gagne haut la main. Cependant, le try catch approche a pris un temps fou. Le point de moi de penser que je fait quelque chose de mal! J'ai aussi mis à jour regex pour traiter les négatifs et les points décimaux.
Résultats pour les mises à jour, C# de référence code:
00:00:51.7390000 for isIntegerParseInt
00:00:03.9110000 for isIntegerRegex
00:00:00.3500000 for isIntegerTryParse
À l'aide de:
static bool isIntegerParseInt(string str) {
try {
int.Parse(str);
return true;
} catch (FormatException e){}
return false;
}
static bool isIntegerRegex(string str) {
return Regex.Match(str, "^-?[0-9]+(\\.[0-9]+)?$").Success;
}
static bool isIntegerTryParse(string str) {
int bob;
return Int32.TryParse(str, out bob);
}
- Je pense que TryParse est la meilleure façon
- Quels sont vos entrées? Attendez-vous que 99% du temps, la chaîne ne peut être un nombre, et seulement 1% du temps, il ne sera pas? Ou est-ce l'inverse? Vous souhaitez optimiser le code de la branche qui est en fait va être exercés dans la plupart des cas.
- Ajouté, puis retirez c# tag. 🙂
- Une petite question à votre regex: "3.0" est un entier? Juste pour moi 3.0 == 3 🙂 Mais je ne connais pas tous vos besoins spécifiques...
- Comunauté wiki sont pour les questions qui n'ont pas une (unique) réponse correcte
- Cette question est C# ou Java? Il y a des contradictions de toute façon.
- si vous êtes à la recherche d'une solution en java, pourquoi voudriez-vous faire C# de repères?
Vous devez vous connecter pour publier un commentaire.
J'ai juste couru quelques repères sur les performances de ces 2 méthodes (Sur Macbook Pro OSX Leopard Java 6). ParseInt est plus rapide. Voici le résultat:
Et voici mon code de référence:
Notez également que votre regex de rejeter les nombres négatifs et la méthode parseInt va les accepter.
-
dans la regex. Ne serait-il pas échouer sur-321
?Ici, c'est notre façon de faire:
Si absolue la performance est la clé, et si vous êtes juste de vérification pour les entiers (et non des nombres à virgule flottante) je soupçonne que itération sur chaque caractère de la chaîne, retourner false si vous rencontrez quelque chose de pas dans la gamme de 0 à 9, sera la plus rapide.
RegEx est un plus généraliste solution ne sera donc probablement pas aussi rapide pour ce cas particulier. Une solution qui déclenche une exception aura quelques frais généraux supplémentaires dans ce cas. TryParse sera légèrement de plus si vous n'avez pas de soins sur la valeur de ce nombre, si oui ou non il est un certain nombre, puisque la conversion d'un nombre doit également avoir lieu.
Pour rien, mais une boucle interne qui a appelé à de nombreuses reprises, les différences entre toutes ces options doivent être insignifiants.
J'avais besoin de refactoriser le code, comme la vôtre, pour se débarrasser de NumberFormatException. La refactorisation de Code:
Comme Java 1.4 gars, je ne connaissais pas java.util.Scanner. J'ai trouvé cet article intéressant:
http://rosettacode.org/wiki/Determine_if_a_string_is_numeric#Java
J'ai personnellement bien aimé la solution avec le scanner, très compact et toujours lisible.
Scanner.nextInt()
semble jeterInputMismatchException
. (même dans la version 1.5)Certains langages, comme le C#, ont un TryParse (ou l'équivalent) qui fonctionne assez bien pour quelque chose comme ça.
Personnellement, je voudrais faire cela si vous voulez vraiment vous simplifier.
Vous pouvez créer une méthode d'extension pour une chaîne de caractères, et de rendre l'ensemble du processus de regarder plus propre...
Vous pouvez ensuite effectuer les opérations suivantes dans votre code...
À l'aide .NET, vous pourriez faire quelque chose comme:
C'est ma mise en œuvre pour vérifier si une chaîne est faite de chiffres:
J'ai comme code:
Mais il sera bien plus lors de la création de Modèle avant de l'utiliser:
S'appliquent, par l'épreuve, nous avons le résultat:
Avec:
Je pense qu'Il pourrait être plus rapide que les solutions précédentes si vous procédez de la manière suivante (Java):
J'ai couru le même code que Asaph exécuté et le résultat a été:
Une énorme différence (contre 1691 ms et 2049 ms sur mon ordinateur). Prendre en compte le fait que cette méthode ne permet pas de valider si la chaîne est nulle, de sorte que vous devriez le faire précédemment (y compris la Chaîne de parage)
Je pense que les gens ici manque un point. L'utilisation de la même motif à plusieurs reprises est très facile d'optimisation. Il suffit d'utiliser un singleton de la répétition. De le faire, dans tous mes tests le try-catch approche ne jamais avoir une meilleure référence que le modèle de l'approche. Avec un succès de test try-catch prend deux fois plus de temps, avec un échec de test il est 6 fois plus lent.
Je l'utiliser mais j'ai bien aimé Asaph rigueur dans son post.
Pendant de longues numéros d'utiliser ceci:
(JAVA)
pour vérifier si le nombre (y compris les float, integer) ou pas
Une version modifiée de ma réponse précédente:
J'ai juste ajouté cette classe pour mon utils:
Pour l'utiliser:
Cette seule analyse de la valeur une fois.
Il fait encore usage de l'exception et le contrôle de flux par des exceptions, mais au moins il est un condensé de ce type de code dans une classe utilitaire, et le code qui l'utilise peut fonctionner plus normalement.
Le problème avec Java par rapport à C#, c'est que C# a des valeurs et passage par référence, de sorte qu'il peut effectivement renvoyer les 2 morceaux de l'information; le drapeau pour indiquer que quelque chose est analysée ou non, et de la valeur analysée. Lorsque nous reutrn >valeur 1 en Java, nous avons besoin de créer un objet pour les tenir, j'ai donc pris que l'approche et les mettre sur le drapeau et la valeur analysée dans un objet.
Échapper à l'analyse est susceptible de gérer cela de manière efficace, et de créer de la valeur et le drapeau sur la pile, et de ne jamais créer cet objet sur le tas, donc je pense que cela va avoir un impact minimal sur les performances.
À ma façon de penser cela donne sur le compromis optimal entre le maintien de flux de contrôle par exception votre code, de bonnes performances, et pas de l'analyse du nombre entier plus d'une fois.
public static boolean CheckIfNumber(numéro de Chaîne){
J'ai eu ce problème avant, mais quand j'ai eu un nombre, puis un personnage, il serait toujours revenir en vrai, je pense que c'est la meilleure manière de le faire. Il suffit de vérifier si chaque char est un nombre. Un peu plus long, mais il prend soin si vous avez de la situation d'un utilisateur saisie "1abc". Pour quelque raison, quand j'ai essayé de try et catch sans itération, il a toujours pensé que c'était un numéro..