solo separador punto por parse mostrar example decimales convertir coma cambiar c# string parsing double

separador - mostrar solo 2 decimales en c#



¿Cómo puedo analizar una cadena con un punto decimal a un doble? (16)

Quiero analizar una cadena como "3.5" a una doble. Sin embargo,

double.Parse("3.5")

rinde 35 y

double.Parse("3.5", System.Globalization.NumberStyles.AllowDecimalPoint)

lanza una FormatException .

Ahora la configuración regional de mi computadora está configurada en alemán, en donde se usa una coma como separador decimal. Puede que tenga que hacer algo con eso y double.Parse() esperando "3,5" como entrada, pero no estoy seguro.

¿Cómo puedo analizar una cadena que contiene un número decimal que puede o no tener el formato especificado en mi configuración regional actual?


Creo que es la mejor respuesta:

public static double StringToDouble(string toDouble) { toDouble = toDouble.Replace(",", "."); //Replace every comma with dot //Count dots in toDouble, and if there is more than one dot, throw an exception. //Value such as "123.123.123" can''t be converted to double int dotCount = 0; foreach (char c in toDouble) if (c == ''.'') dotCount++; //Increments dotCount for each dot in toDouble if (dotCount > 1) throw new Exception(); //If in toDouble is more than one dot, it means that toCount is not a double string left = toDouble.Split(''.'')[0]; //Everything before the dot string right = toDouble.Split(''.'')[1]; //Everything after the dot int iLeft = int.Parse(left); //Convert strings to ints int iRight = int.Parse(right); //We must use Math.Pow() instead of ^ double d = iLeft + (iRight * Math.Pow(10, -(right.Length))); return d; }


Creo que no es posible una conversión 100% correcta, si el valor proviene de una entrada del usuario. por ejemplo, si el valor es 123.456, puede ser una agrupación o puede ser un punto decimal. Si realmente necesita 100%, debe describir su formato y lanzar una excepción si no es correcto.

Pero mejoré el código de JanW, así que avanzamos un poco más al 100%. La idea detrás es que si el último separador es un groupSeperator, sería más un tipo entero que un doble.

El código agregado está en el primero si de GetDouble .

void Main() { List<string> inputs = new List<string>() { "1.234.567,89", "1 234 567,89", "1 234 567.89", "1,234,567.89", "1234567,89", "1234567.89", "123456789", "123.456.789", "123,456,789," }; foreach(string input in inputs) { Console.WriteLine(GetDouble(input,0d)); } } public static double GetDouble(string value, double defaultValue) { double result; string output; // Check if last seperator==groupSeperator string groupSep = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator; if (value.LastIndexOf(groupSep) + 4 == value.Count()) { bool tryParse = double.TryParse(value, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.CurrentCulture, out result); result = tryParse ? result : defaultValue; } else { // Unify string (no spaces, only . ) output = value.Trim().Replace(" ", string.Empty).Replace(",", "."); // Split it on points string[] split = output.Split(''.''); if (split.Count() > 1) { // Take all parts except last output = string.Join(string.Empty, split.Take(split.Count()-1).ToArray()); // Combine token parts with last part output = string.Format("{0}.{1}", output, split.Last()); } // Parse double invariant result = double.Parse(output, System.Globalization.CultureInfo.InvariantCulture); } return result; }


El siguiente código hace el trabajo en cualquier escenario. Está un poco analizando.

List<string> inputs = new List<string>() { "1.234.567,89", "1 234 567,89", "1 234 567.89", "1,234,567.89", "123456789", "1234567,89", "1234567.89", }; string output; foreach (string input in inputs) { // Unify string (no spaces, only .) output = input.Trim().Replace(" ", "").Replace(",", "."); // Split it on points string[] split = output.Split(''.''); if (split.Count() > 1) { // Take all parts except last output = string.Join("", split.Take(split.Count()-1).ToArray()); // Combine token parts with last part output = string.Format("{0}.{1}", output, split.Last()); } // Parse double invariant double d = double.Parse(output, CultureInfo.InvariantCulture); Console.WriteLine(d); }


El truco es usar la cultura invariante, para analizar el punto en todas las culturas.

double.Parse("3.5", System.Globalization.NumberStyles.AllowDecimalPoint, System.Globalization.NumberFormatInfo.InvariantInfo);


En lugar de tener que especificar una configuración regional en todos los análisis, prefiero establecer una configuración regional amplia para la aplicación, aunque si los formatos de cadena no son consistentes en toda la aplicación, es posible que esto no funcione.

CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("pt-PT"); CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("pt-PT");

Al definir esto al comienzo de su aplicación, todos los análisis dobles esperan una coma como delimitador decimal. Puede establecer una configuración regional adecuada para que el separador de decimales y de miles se ajuste a las cadenas que está analizando.


Es difícil sin especificar qué separador decimal buscar, pero si lo haces, esto es lo que estoy usando:

public static double Parse(string str, char decimalSep) { string s = GetInvariantParseString(str, decimalSep); return double.Parse(s, System.Globalization.CultureInfo.InvariantCulture); } public static bool TryParse(string str, char decimalSep, out double result) { // NumberStyles.Float | NumberStyles.AllowThousands got from Reflector return double.TryParse(GetInvariantParseString(str, decimalSep), NumberStyles.Float | NumberStyles.AllowThousands, System.Globalization.CultureInfo.InvariantCulture, out result); } private static string GetInvariantParseString(string str, char decimalSep) { str = str.Replace(" ", ""); if (decimalSep != ''.'') str = SwapChar(str, decimalSep, ''.''); return str; } public static string SwapChar(string value, char from, char to) { if (value == null) throw new ArgumentNullException("value"); StringBuilder builder = new StringBuilder(); foreach (var item in value) { char c = item; if (c == from) c = to; else if (c == to) c = from; builder.Append(c); } return builder.ToString(); } private static void ParseTestErr(string p, char p_2) { double res; bool b = TryParse(p, p_2, out res); if (b) throw new Exception(); } private static void ParseTest(double p, string p_2, char p_3) { double d = Parse(p_2, p_3); if (d != p) throw new Exception(); } static void Main(string[] args) { ParseTest(100100100.100, "100.100.100,100", '',''); ParseTest(100100100.100, "100,100,100.100", ''.''); ParseTest(100100100100, "100.100.100.100", '',''); ParseTest(100100100100, "100,100,100,100", ''.''); ParseTestErr("100,100,100,100", '',''); ParseTestErr("100.100.100.100", ''.''); ParseTest(100100100100, "100 100 100 100.0", ''.''); ParseTest(100100100.100, "100 100 100.100", ''.''); ParseTest(100100100.100, "100 100 100,100", '',''); ParseTest(100100100100, "100 100 100,100", ''.''); ParseTest(1234567.89, "1.234.567,89", '',''); ParseTest(1234567.89, "1 234 567,89", '',''); ParseTest(1234567.89, "1 234 567.89", ''.''); ParseTest(1234567.89, "1,234,567.89", ''.''); ParseTest(1234567.89, "1234567,89", '',''); ParseTest(1234567.89, "1234567.89", ''.''); ParseTest(123456789, "123456789", ''.''); ParseTest(123456789, "123456789", '',''); ParseTest(123456789, "123.456.789", '',''); ParseTest(1234567890, "1.234.567.890", '',''); }

Esto debería funcionar con cualquier cultura. Correctamente no analiza las cadenas que tienen más de un separador decimal, a diferencia de las implementaciones que reemplazan en lugar de intercambiar.


Lo siguiente es menos eficiente, pero uso esta lógica. Esto es válido solo si tiene dos dígitos después del punto decimal.

double val; if (temp.Text.Split(''.'').Length > 1) { val = double.Parse(temp.Text.Split(''.'')[0]); if (temp.Text.Split(''.'')[1].Length == 1) val += (0.1 * double.Parse(temp.Text.Split(''.'')[1])); else val += (0.01 * double.Parse(temp.Text.Split(''.'')[1])); } else val = double.Parse(RR(temp.Text));


Mira, cada respuesta anterior que propone escribir un reemplazo de cadena por una cadena constante solo puede ser incorrecta. ¿Por qué? ¡Porque no respetas la configuración regional de Windows! Windows le garantiza al usuario la libertad de establecer el carácter de separación que desee. S / He puede abrir el panel de control, acceder al panel de región, hacer clic en avanzado y cambiar el carácter en cualquier momento. Incluso durante tu ejecución del programa. Piense en esto. Una buena solución debe ser consciente de esto.

Entonces, primero tendrá que preguntarse a sí mismo, de dónde viene este número, que desea analizar. Si proviene de entrada en .NET Framework no hay problema, porque estará en el mismo formato. Pero tal vez venía del exterior, tal vez de un servidor externo, tal vez de un DB antiguo que solo admite propiedades de cadenas. Allí, el administrador de db debería haber dado una regla en qué formato se deben almacenar los números. Si sabe, por ejemplo, que será un DB de EE. UU. Con formato de EE. UU., Puede usar este fragmento de código:

CultureInfo usCulture = new CultureInfo("en-US"); NumberFormatInfo dbNumberFormat = usCulture.NumberFormat; decimal number = decimal.Parse(db.numberString, dbNumberFormat);

Esto funcionará bien en cualquier parte del mundo. Y por favor no use ''Convert.ToXxxx''. La clase ''Convertir'' está pensada solo como una base para conversiones en cualquier dirección. Además: también puedes utilizar el mecanismo similar para DateTimes.


Multiplica el número y luego divídelo por lo que multiplicaste por antes.

Por ejemplo,

perc = double.Parse("3.555)*1000; result = perc/1000


No pude escribir un comentario, entonces escribo aquí:

double.Parse ("3.5", CultureInfo.InvariantCulture) no es una buena idea, porque en Canadá escribimos 3,5 en lugar de 3.5 y esta función nos da 35 como resultado.

Probé ambos en mi computadora:

double.Parse("3.5", CultureInfo.InvariantCulture) --> 3.5 OK double.Parse("3,5", CultureInfo.InvariantCulture) --> 35 not OK

Esta es una forma correcta que Pierre-Alain Vigeant menciona

public static double GetDouble(string value, double defaultValue) { double result; // Try parsing in the current culture if (!double.TryParse(value, System.Globalization.NumberStyles.Any, CultureInfo.CurrentCulture, out result) && // Then try in US english !double.TryParse(value, System.Globalization.NumberStyles.Any, CultureInfo.GetCultureInfo("en-US"), out result) && // Then in neutral language !double.TryParse(value, System.Globalization.NumberStyles.Any, CultureInfo.InvariantCulture, out result)) { result = defaultValue; } return result; }


También mejoré el código de @JanW ...

Lo necesito para formatear resultados de instrumentos médicos, y también envían "> 1000", "23.3e02", "350E-02" y "NEGATIVO".

private string FormatResult(string vResult) { string output; string input = vResult; // Unify string (no spaces, only .) output = input.Trim().Replace(" ", "").Replace(",", "."); // Split it on points string[] split = output.Split(''.''); if (split.Count() > 1) { // Take all parts except last output = string.Join("", split.Take(split.Count() - 1).ToArray()); // Combine token parts with last part output = string.Format("{0}.{1}", output, split.Last()); } string sfirst = output.Substring(0, 1); try { if (sfirst == "<" || sfirst == ">") { output = output.Replace(sfirst, ""); double res = Double.Parse(output); return String.Format("{1}{0:0.####}", res, sfirst); } else { double res = Double.Parse(output); return String.Format("{0:0.####}", res); } } catch { return output; } }


Usualmente uso una función multicultural para analizar la entrada del usuario, principalmente porque si alguien está acostumbrado al teclado numérico y está utilizando un idioma que usa una coma como separador decimal, esa persona usará el punto del teclado numérico en lugar de una coma.

public static double GetDouble(string value, double defaultValue) { double result; //Try parsing in the current culture if (!double.TryParse(value, System.Globalization.NumberStyles.Any, CultureInfo.CurrentCulture, out result) && //Then try in US english !double.TryParse(value, System.Globalization.NumberStyles.Any, CultureInfo.GetCultureInfo("en-US"), out result) && //Then in neutral language !double.TryParse(value, System.Globalization.NumberStyles.Any, CultureInfo.InvariantCulture, out result)) { result = defaultValue; } return result; }

Sin embargo, ten cuidado, los comentarios de @nikie son ciertos. En mi defensa, uso esta función en un entorno controlado donde sé que la cultura puede ser en-US, en-CA o fr-CA. Uso esta función porque en francés, utilizamos la coma como un separador decimal, pero cualquiera que haya trabajado en finanzas siempre usará el separador decimal en el teclado numérico, pero este es un punto, no una coma. Entonces, incluso en la cultura fr-CA, necesito analizar el número que tendrá un punto como el separador decimal.


Double.Parse("3,5".Replace('','', ''.''), CultureInfo.InvariantCulture)

Reemplace la coma con un punto antes de analizar. Útil en países con una coma como separador decimal. Piense en limitar la entrada del usuario (si es necesario) a una coma o punto.


System.Globalization.CultureInfo ci = System.Globalization.CultureInfo.CurrentCulture; string _pos = dblstr.Replace(".", ci.NumberFormat.NumberDecimalSeparator).Replace(",", ci.NumberFormat.NumberDecimalSeparator); double _dbl = double.Parse(_pos);


double.Parse("3.5", CultureInfo.InvariantCulture)


string testString1 = "2,457"; string testString2 = "2.457"; double testNum = 0.5; char decimalSepparator; decimalSepparator = testNum.ToString()[1]; Console.WriteLine(double.Parse(testString1.Replace(''.'', decimalSepparator).Replace('','', decimalSepparator))); Console.WriteLine(double.Parse(testString2.Replace(''.'', decimalSepparator).Replace('','', decimalSepparator)));