Comparteix a través de


Análisis de cadenas numéricas en .NET

Todos los tipos numéricos tienen dos métodos de análisis estáticos y ParseTryParse, que puede usar para convertir la representación de cadena de un número en un tipo numérico. Estos métodos permiten analizar las cadenas que se generaron mediante las cadenas de formato documentadas en Cadenas de formato numérico estándar y Cadenas de formato numérico personalizado. De forma predeterminada, los Parse métodos y TryParse pueden convertir correctamente cadenas que contienen dígitos decimales enteros solo a valores enteros. Pueden convertir correctamente cadenas que contienen dígitos decimales enteros y fraccionarios, separadores de grupo y separadores decimales a valores de punto flotante. El Parse método produce una excepción si se produce un error en la operación, mientras que el TryParse método devuelve false.

Nota:

A partir de .NET 7, los tipos numéricos de .NET también implementan la System.IParsable<TSelf> interfaz , que define los IParsable<TSelf>.Parse métodos y IParsable<TSelf>.TryParse .

Análisis sintáctico y proveedores de formato

Normalmente, las representaciones de cadena de valores numéricos difieren según la referencia cultural. Los elementos de cadenas numéricas, como símbolos de moneda, separadores de grupo (o miles) y separadores decimales, varían según la referencia cultural. Los métodos de análisis utilizan implícita o explícitamente un proveedor de formato que reconoce estas variaciones específicas de la cultura. Si no se especifica ningún proveedor de formato en una llamada al método Parse o TryParse, se utiliza el proveedor de formato asociado a la cultura actual (el objeto NumberFormatInfo devuelto por la propiedad NumberFormatInfo.CurrentInfo).

Un proveedor de formato se representa mediante una IFormatProvider implementación. Esta interfaz tiene un único miembro, el GetFormat método , cuyo único parámetro es un Type objeto que representa el tipo al que se va a dar formato. Este método devuelve el objeto que proporciona información de formato. .NET admite las dos IFormatProvider implementaciones siguientes para analizar cadenas numéricas:

En el ejemplo siguiente se intenta convertir cada cadena de una matriz en un Double valor . Primero intenta analizar la cadena mediante un proveedor de formato que refleje las convenciones de la cultura inglesa (Estados Unidos). Si esta operación produce un FormatException, intenta analizar la cadena mediante un proveedor de formato que refleje las convenciones de la cultura francesa (Francia).

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      string[] values = { "1,304.16", "$1,456.78", "1,094", "152",
                          "123,45 €", "1 304,16", "Ae9f" };
      double number;
      CultureInfo culture = null;

      foreach (string value in values) {
         try {
            culture = CultureInfo.CreateSpecificCulture("en-US");
            number = Double.Parse(value, culture);
            Console.WriteLine($"{culture.Name}: {value} --> {number}");
         }
         catch (FormatException) {
            Console.WriteLine($"{culture.Name}: Unable to parse '{value}'.");
            culture = CultureInfo.CreateSpecificCulture("fr-FR");
            try {
               number = Double.Parse(value, culture);
               Console.WriteLine($"{culture.Name}: {value} --> {number}");
            }
            catch (FormatException) {
               Console.WriteLine($"{culture.Name}: Unable to parse '{value}'.");
            }
         }
         Console.WriteLine();
      }
   }
}
// The example displays the following output:
//    en-US: 1,304.16 --> 1304.16
//
//    en-US: Unable to parse '$1,456.78'.
//    fr-FR: Unable to parse '$1,456.78'.
//
//    en-US: 1,094 --> 1094
//
//    en-US: 152 --> 152
//
//    en-US: Unable to parse '123,45 €'.
//    fr-FR: Unable to parse '123,45 €'.
//
//    en-US: Unable to parse '1 304,16'.
//    fr-FR: 1 304,16 --> 1304.16
//
//    en-US: Unable to parse 'Ae9f'.
//    fr-FR: Unable to parse 'Ae9f'.
Imports System.Globalization

Module Example
    Public Sub Main()
        Dim values() As String = {"1,304.16", "$1,456.78", "1,094", "152",
                                   "123,45 €", "1 304,16", "Ae9f"}
        Dim number As Double
        Dim culture As CultureInfo = Nothing

        For Each value As String In values
            Try
                culture = CultureInfo.CreateSpecificCulture("en-US")
                number = Double.Parse(value, culture)
                Console.WriteLine("{0}: {1} --> {2}", culture.Name, value, number)
            Catch e As FormatException
                Console.WriteLine("{0}: Unable to parse '{1}'.",
                                  culture.Name, value)
                culture = CultureInfo.CreateSpecificCulture("fr-FR")
                Try
                    number = Double.Parse(value, culture)
                    Console.WriteLine("{0}: {1} --> {2}", culture.Name, value, number)
                Catch ex As FormatException
                    Console.WriteLine("{0}: Unable to parse '{1}'.",
                                      culture.Name, value)
                End Try
            End Try
            Console.WriteLine()
        Next
    End Sub
End Module
' The example displays the following output:
'    en-US: 1,304.16 --> 1304.16
'    
'    en-US: Unable to parse '$1,456.78'.
'    fr-FR: Unable to parse '$1,456.78'.
'    
'    en-US: 1,094 --> 1094
'    
'    en-US: 152 --> 152
'    
'    en-US: Unable to parse '123,45 €'.
'    fr-FR: Unable to parse '123,45 €'.
'    
'    en-US: Unable to parse '1 304,16'.
'    fr-FR: 1 304,16 --> 1304.16
'    
'    en-US: Unable to parse 'Ae9f'.
'    fr-FR: Unable to parse 'Ae9f'.

Análisis y valores NumberStyles

Los elementos de estilo (como el espacio en blanco, los separadores de grupo y el separador decimal) que la operación de análisis puede controlar se definen mediante un NumberStyles valor de enumeración. De forma predeterminada, las cadenas que representan valores enteros se analizan mediante el NumberStyles.Integer valor , que solo permite dígitos numéricos, espacios en blanco iniciales y finales, y un signo inicial. Las cadenas que representan valores de punto flotante se analizan mediante una combinación de los NumberStyles.Float valores y NumberStyles.AllowThousands ; este estilo compuesto permite dígitos decimales junto con el espacio en blanco inicial y final, un signo inicial, un separador decimal, un separador de grupo y un exponente. Al llamar a una sobrecarga del método Parse o TryParse, que incluye un parámetro de tipo NumberStyles, y establecer uno o más indicadores NumberStyles, puede controlar los elementos de estilo que pueden estar presentes en la cadena para que la operación de análisis tenga éxito.

Por ejemplo, una cadena que contiene un separador de grupo no se puede convertir en un Int32 valor mediante el Int32.Parse(String) método . Sin embargo, la conversión se realiza correctamente si usa la NumberStyles.AllowThousands marca , como se muestra en el ejemplo siguiente.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      string value = "1,304";
      int number;
      IFormatProvider provider = CultureInfo.CreateSpecificCulture("en-US");
      if (Int32.TryParse(value, out number))
         Console.WriteLine($"{value} --> {number}");
      else
         Console.WriteLine($"Unable to convert '{value}'");

      if (Int32.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands,
                        provider, out number))
         Console.WriteLine($"{value} --> {number}");
      else
         Console.WriteLine($"Unable to convert '{value}'");
   }
}
// The example displays the following output:
//       Unable to convert '1,304'
//       1,304 --> 1304
Imports System.Globalization

Module Example
    Public Sub Main()
        Dim value As String = "1,304"
        Dim number As Integer
        Dim provider As IFormatProvider = CultureInfo.CreateSpecificCulture("en-US")
        If Int32.TryParse(value, number) Then
            Console.WriteLine("{0} --> {1}", value, number)
        Else
            Console.WriteLine("Unable to convert '{0}'", value)
        End If

        If Int32.TryParse(value, NumberStyles.Integer Or NumberStyles.AllowThousands,
                          provider, number) Then
            Console.WriteLine("{0} --> {1}", value, number)
        Else
            Console.WriteLine("Unable to convert '{0}'", value)
        End If
    End Sub
End Module
' The example displays the following output:
'       Unable to convert '1,304'
'       1,304 --> 1304

Advertencia

La operación de análisis siempre usa las convenciones de formato de una referencia cultural determinada. Si no especifica una referencia cultural pasando un objeto CultureInfo o NumberFormatInfo, se utiliza la referencia cultural asociada al hilo actual.

En la tabla siguiente se enumeran los miembros de la NumberStyles enumeración y se describe el efecto que tienen en la operación de análisis.

Valor de NumberStyles Efecto en la cadena a analizar
NumberStyles.None Solo se permiten dígitos numéricos.
NumberStyles.AllowDecimalPoint Se permiten el separador decimal y los dígitos fraccionarios. Para los valores enteros, solo se permite cero como un dígito fraccionario. Los separadores decimales válidos se determinan mediante la NumberFormatInfo.NumberDecimalSeparator propiedad o NumberFormatInfo.CurrencyDecimalSeparator .
NumberStyles.AllowExponent El carácter "e" o "E" se puede usar para indicar la notación exponencial. Para obtener más información, consulte NumberStyles.
NumberStyles.AllowLeadingWhite Se permite el espacio en blanco inicial.
NumberStyles.AllowTrailingWhite Se permite el espacio en blanco final.
NumberStyles.AllowLeadingSign Un signo positivo o negativo puede preceder a dígitos numéricos.
NumberStyles.AllowTrailingSign Un signo positivo o negativo puede seguir dígitos numéricos.
NumberStyles.AllowParentheses Los paréntesis se pueden usar para indicar valores negativos.
NumberStyles.AllowThousands Se permite el separador de grupo. El carácter separador de grupo está determinado por la propiedad NumberFormatInfo.NumberGroupSeparator o NumberFormatInfo.CurrencyGroupSeparator.
NumberStyles.AllowCurrencySymbol Se permite el símbolo de moneda. El símbolo de moneda se define mediante la NumberFormatInfo.CurrencySymbol propiedad .
NumberStyles.AllowHexSpecifier La cadena que se va a analizar se interpreta como un número hexadecimal. Puede incluir los dígitos hexadecimales 0-9, A-F y a-f. Esta marca solo se puede usar para analizar valores enteros.
NumberStyles.AllowBinarySpecifier La cadena que se va a analizar se interpreta como un número binario. Puede incluir los dígitos binarios 0 y 1. Esta marca solo se puede usar para analizar valores enteros.

Además, la NumberStyles enumeración proporciona los siguientes estilos compuestos, que incluyen varias NumberStyles marcas.

Valor compuesto de estilos de número Incluye miembros
NumberStyles.Integer Incluye los estilos NumberStyles.AllowLeadingWhite, NumberStyles.AllowTrailingWhite y NumberStyles.AllowLeadingSign. Este es el estilo predeterminado que se usa para analizar los valores enteros.
NumberStyles.Number Incluye los NumberStyles.AllowLeadingWhiteestilos , NumberStyles.AllowTrailingWhite, NumberStyles.AllowLeadingSign, NumberStyles.AllowTrailingSign, NumberStyles.AllowDecimalPointy NumberStyles.AllowThousands .
NumberStyles.Float Incluye los estilos NumberStyles.AllowLeadingWhite, NumberStyles.AllowTrailingWhite, NumberStyles.AllowLeadingSign, NumberStyles.AllowDecimalPoint y NumberStyles.AllowExponent.
NumberStyles.Currency Incluye todos los estilos excepto NumberStyles.AllowExponent y NumberStyles.AllowHexSpecifier.
NumberStyles.Any Incluye todos los estilos excepto NumberStyles.AllowHexSpecifier.
NumberStyles.HexNumber Incluye los NumberStyles.AllowLeadingWhite estilos, NumberStyles.AllowTrailingWhite y NumberStyles.AllowHexSpecifier.
NumberStyles.BinaryNumber Incluye los NumberStyles.AllowLeadingWhite , NumberStyles.AllowTrailingWhite y NumberStyles.AllowBinarySpecifier estilos.

Análisis sintáctico de BigIntegers binarios y hexadecimales

Al analizar BigInteger con las AllowHexSpecifier marcas o AllowBinarySpecifier , la cadena de entrada se interpreta como un número hexadecimal o binario de exactamente la longitud que tiene la cadena. Por ejemplo, el análisis de "11" como un BigInteger binario produce -1, porque esa es la interpretación de 11 como un valor en complemento a dos firmado con exactamente 2 dígitos. Si desea un resultado positivo, agregue un valor inicial 0, como "011" , que se analiza como 3.

Análisis sintáctico y dígitos Unicode

El estándar Unicode define puntos de código para dígitos en varios sistemas de escritura. Por ejemplo, los puntos de código de U+0030 a U+0039 representan los dígitos latinos básicos del 0 al 9, los puntos de código de U+09E6 a U+09EF representan los dígitos de Bangla de 0 a 9 y los puntos de código de U+FF10 a U+FF19 representan los dígitos Fullwidth del 0 al 9. Sin embargo, los únicos dígitos numéricos reconocidos por los métodos de análisis son los dígitos latinos básicos 0-9 con puntos de código de U+0030 a U+0039. Si a un método de análisis numérico se le pasa una cadena que contiene cualquier otro dígito, el método lanza una excepción FormatException.

En el ejemplo siguiente se usa el Int32.Parse método para analizar cadenas que constan de dígitos en diferentes sistemas de escritura. Como se muestra en la salida del ejemplo, el intento de analizar los dígitos latinos básicos se realiza correctamente, pero se produce un error al intentar analizar los dígitos Fullwidth, Árabe-Indic y Bangla.

using System;

public class Example
{
   public static void Main()
   {
      string value;
      // Define a string of basic Latin digits 1-5.
      value = "\u0031\u0032\u0033\u0034\u0035";
      ParseDigits(value);

      // Define a string of Fullwidth digits 1-5.
      value = "\uFF11\uFF12\uFF13\uFF14\uFF15";
      ParseDigits(value);

      // Define a string of Arabic-Indic digits 1-5.
      value = "\u0661\u0662\u0663\u0664\u0665";
      ParseDigits(value);

      // Define a string of Bangla digits 1-5.
      value = "\u09e7\u09e8\u09e9\u09ea\u09eb";
      ParseDigits(value);
   }

   static void ParseDigits(string value)
   {
      try {
         int number = Int32.Parse(value);
         Console.WriteLine($"'{value}' --> {number}");
      }
      catch (FormatException) {
         Console.WriteLine($"Unable to parse '{value}'.");
      }
   }
}
// The example displays the following output:
//       '12345' --> 12345
//       Unable to parse '12345'.
//       Unable to parse '١٢٣٤٥'.
//       Unable to parse '১২৩৪৫'.
Module Example
    Public Sub Main()
        Dim value As String
        ' Define a string of basic Latin digits 1-5.
        value = ChrW(&h31) + ChrW(&h32) + ChrW(&h33) + ChrW(&h34) + ChrW(&h35)
        ParseDigits(value)

        ' Define a string of Fullwidth digits 1-5.
        value = ChrW(&hff11) + ChrW(&hff12) + ChrW(&hff13) + ChrW(&hff14) + ChrW(&hff15)
        ParseDigits(value)

        ' Define a string of Arabic-Indic digits 1-5.
        value = ChrW(&h661) + ChrW(&h662) + ChrW(&h663) + ChrW(&h664) + ChrW(&h665)
        ParseDigits(value)

        ' Define a string of Bangla digits 1-5.
        value = ChrW(&h09e7) + ChrW(&h09e8) + ChrW(&h09e9) + ChrW(&h09ea) + ChrW(&h09eb)
        ParseDigits(value)
    End Sub

    Sub ParseDigits(value As String)
        Try
            Dim number As Integer = Int32.Parse(value)
            Console.WriteLine("'{0}' --> {1}", value, number)
        Catch e As FormatException
            Console.WriteLine("Unable to parse '{0}'.", value)
        End Try
    End Sub
End Module
' The example displays the following output:
'       '12345' --> 12345
'       Unable to parse '12345'.
'       Unable to parse '١٢٣٤٥'.
'       Unable to parse '১২৩৪৫'.

Consulte también