Vea mi respuesta: String.Format()con 'G' debería obtener lo que desea ... He actualizado mi respuesta con un enlace a formatos numéricos estándar. Muy útil
Dog Ears
3
Se puede convertir un decimal doubley el valor predeterminado ToStringpara doble emite los ceros finales. lea esto
Shimmy Weitzhandler
2
Y probablemente costará menos rendimiento (interms de gran cantidad de registros) que pasar la "G" como formato de cadena a la ToStringfunción.
Shimmy Weitzhandler
44
No debe convertir un decimal a un doble, perderá importancia y puede introducir el poder de dos imprecisiones de redondeo.
kristianp
Respuestas:
167
¿No es tan simple como esto, si la entrada ES una cadena? Puedes usar uno de estos:
Actualización Consulte los formatos numéricos estándar . He tenido que establecer explícitamente el especificador de precisión en 29, ya que los documentos indican claramente:
Sin embargo, si el número es un decimal y se omite el especificador de precisión, siempre se usa la notación de punto fijo y se conservan los ceros finales
Tenga cuidado con valores como 0.000001. El formato G29 los presentará de la forma más corta posible, por lo que cambiará a la notación exponencial. string.Format("{0:G29}", decimal.Parse("0.00000001",System.Globalization.CultureInfo.GetCultureInfo("en-US")))dará "1E-08" como resultado.
De todas las respuestas, ha tenido los menos pasos involucrados. Gracias Dog Ears.
Zo tiene
44
var d = 2.0m; d.ToString ("G");
Dave Hillier el
3
@Dave Hillier - Ya veo, he corregido mi respuesta. Salud. [añadido explícito 'especificador de precisión']
Dog Ears
16
Tenga cuidado con valores como 0.000001. El formato G29 los presentará de la forma más corta posible, por lo que cambiará a la notación exponencial. string.Format ("{0: G29}", decimal.Parse ("0.00000001", System.Globalization.CultureInfo.GetCultureInfo ("en-US"))) dará "1E-08" como resultado
Konrad
15
@Konrad: ¿hay alguna forma de evitar la notación científica para los números que tienen 5 o 6 decimales?
Jill
202
Me encontré con el mismo problema, pero en un caso en el que no tengo control de la salida a la cadena, que fue atendida por una biblioteca. Después de buscar detalles en la implementación del tipo Decimal (ver http://msdn.microsoft.com/en-us/library/system.decimal.getbits.aspx ), se me ocurrió un buen truco (aquí como una extensión método):
La parte exponente del decimal se reduce a lo que se necesita. Llamar a ToString () en el decimal de salida escribirá el número sin ningún 0 final. Por ejemplo
Esta respuesta es propia porque, a diferencia de cualquier otra respuesta sobre esta pregunta (e incluso todo el tema) es realmente FUNCIONA y hace lo que el OP está pidiendo.
Coxy
2
¿es el número de 0s una cantidad exacta aquí o solo para cubrir los valores más esperados?
Simon_Weaver
3
MSDN declara "El factor de escala es implícitamente el número 10, elevado a un exponente que varía de 0 a 28", que entiendo como el número decimal tendrá como máximo 28 dígitos más allá del punto decimal. Cualquier número de ceros> = 28 debería funcionar.
Thomas Materna
2
¡Esta es la mejor respuesta! El número en la respuesta tiene 34 cifras, 1seguidas por 33 0-s, pero eso crea exactamente la misma decimalinstancia que un número con 29 cifras, una 1y 28 0-s. Justo como dijo @ThomasMaterna en su comentario. No System.Decimalpuede tener más de 29 cifras (los números con dígitos iniciales mayores que 79228...solo pueden tener 28 cifras en total) Si desea más ceros al final, multiplique por en 1.000...mlugar de dividir. Además, Math.Roundpuede cortar algunos ceros, por ejemplo , Math.Round(27.40000m, 2)da 27.40m, por lo que solo queda un cero.
Jeppe Stig Nielsen
2
Gran truco, pero NO funciona en Mono y no está garantizado para funcionar en versiones de funciones de .NET
No es una respuesta No está eliminando los ceros finales, está eliminando la precisión. El método propuesto num1.ToString("0.##")debería devolver 13.1534545765(sin cambios) porque no hay ceros finales.
Jan 'splite' K.
Y es exactamente por eso que estoy mostrando las respuestas a mis tres entradas propuestas para que los usuarios puedan ver cómo funciona mi solución.
Fizzix
No responde la pregunta incluso si enumera las entradas propuestas.
Dave Friedel
2
Lo votaría 10 veces si pudiera. ¡Exactamente lo que necesitaba!
SubqueryCrunch
1
Respuesta perfecta a la pregunta. La mejor respuesta en mi opinión. El comentario de que elimina la precisión es correcto, pero esa no era la pregunta. Lo más importante: es lo que necesito. Mis usuarios suelen ingresar números enteros, tal vez algo así como 2.5, pero necesito admitir 3 dígitos más allá del punto decimal. Así que quiero darles lo que ingresaron, no con un montón de ceros que no ingresaron. por ejemplo, Console.Write ($ "num3 = {num3: 0. ##}"); => num3 = 30
Tenga en cuenta que si ves así 0m, el resultado de su código es una cadena vacía en lugar de "0".
Sam
2
Si. Debería ser "0. ########".
PRMan
2
Un enfoque de muy bajo nivel, pero creo que esta sería la forma más eficaz utilizando solo cálculos enteros rápidos (y sin métodos lentos de análisis de cadenas y sensibles a la cultura):
publicstaticdecimalNormalize(thisdecimal d){int[] bits =decimal.GetBits(d);int sign = bits[3]&(1<<31);int exp =(bits[3]>>16)&0x1f;uint a =(uint)bits[2];// Top bitsuint b =(uint)bits[1];// Middle bitsuint c =(uint)bits[0];// Bottom bitswhile(exp >0&&((a %5)*6+(b %5)*6+ c)%10==0){uint r;
a =DivideBy10((uint)0, a,out r);
b =DivideBy10(r, b,out r);
c =DivideBy10(r, c,out r);
exp--;}
bits[0]=(int)c;
bits[1]=(int)b;
bits[2]=(int)a;
bits[3]=(exp <<16)| sign;returnnewdecimal(bits);}privatestaticuintDivideBy10(uint highBits,uint lowBits,outuint remainder){ulong total = highBits;
total <<=32;
total = total |(ulong)lowBits;
remainder =(uint)(total %10L);return(uint)(total /10L);}
@Damien, sí, y tenga en cuenta que para estos propósitos (no sentirá nada a menos que haga mil millones de registros), primero porque el doble es más rápido, segundo, porque pasar un formato de cadena a la función ToString cuesta más rendimiento que no pasando params. de nuevo, no sentirá nada a menos que trabaje en miles de millones de registros.
Shimmy Weitzhandler
1
No tiene que especificar G, porque double.ToStringelimina los ceros finales de forma predeterminada.
Shimmy Weitzhandler
44
Tenga cuidado con valores como 0.000001. Estos se presentarán en la notación exponencial. double.Parse ("0.00000001", System.Globalization.CultureInfo.GetCultureInfo ("en-US")). ToString () dará "1E-08" como resultado
Konrad
17
NUNCA hagas esto. Por lo general, la razón por la que tiene un decimal es porque está representando un número con precisión (no aproximadamente como lo hace un doble). De acuerdo, este error de coma flotante es probablemente bastante pequeño, pero podría dar lugar a mostrar números incorrectos, no obstante
Adam Tegen el
2
¡Ay, convertir un tipo de datos de 128 bits (decimal) en un tipo de datos de 64 bits (doble) para formatear, no es una buena idea!
Depende de lo que represente su número y de cómo desee administrar los valores: ¿es una moneda, necesita redondeo o truncamiento, necesita este redondeo solo para mostrar?
Si para visualización, considere formatear los números son x.ToString ("")
privatestaticdecimalTrim(thisdecimalvalue){var s =value.ToString(CultureInfo.InvariantCulture);return s.Contains(CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator)?Decimal.Parse(s.TrimEnd('0'),CultureInfo.InvariantCulture):value;}privatestaticdecimal?Trim(thisdecimal?value){returnvalue.HasValue?(decimal?)value.Value.Trim():null;}privatestaticvoidMain(string[] args){Console.WriteLine("=>{0}",1.0000m.Trim());Console.WriteLine("=>{0}",1.000000023000m.Trim());Console.WriteLine("=>{0}",((decimal?)1.000000023000m).Trim());Console.WriteLine("=>{0}",((decimal?)null).Trim());}
(I) -> Analiza el valor decimal de cualquier fuente de cadena.
(II) -> Primero: Cast para duplicar esto, eliminar los ceros finales. Segundo: Otro conversión a decimal porque no existe conversión implícita de decimal a doble y viceversa)
Asume todos los valores que cabrían en un decimal, caben en un doble. Esto puede causar una Excepción de desbordamiento. También puede perder precisión.
¿Qué pasa con las configuraciones regionales que no usan '.'?
Martin Mulder
no es una opción en comparación con otros enfoques dentro de esta publicación. Convertir en cadena y viceversa siempre es una mala opción para manipular números (al menos debido a la configuración regional)
Vladimir Semashkin
-11
intenta así
string s ="2.4200";
s = s.TrimStart('0').TrimEnd('0','.');
puede usar el subString()método para eso, pero de acuerdo con la pregunta publicada aquí, no veo ningún requisito como ese =)
Singleton
2
¿Qué pasa con las configuraciones regionales que no usan '.'
Dave Hillier el
10
Esto falla miserablemente para los números que son un múltiplo par de 10.0.
Ben Voigt
1
Lo que dijo @BenVoigt es completamente correcto, ya "12300.00"que se recortará un examen "123". Otro efecto que parece indeseable es que algunos números, como los que "0.00"se recortan hasta la cadena vacía ""(aunque este número es un caso especial de ser un "múltiplo de 10.0" integral).
String.Format()
con 'G' debería obtener lo que desea ... He actualizado mi respuesta con un enlace a formatos numéricos estándar. Muy útildouble
y el valor predeterminadoToString
para doble emite los ceros finales. lea estoToString
función.Respuestas:
¿No es tan simple como esto, si la entrada ES una cadena? Puedes usar uno de estos:
Esto debería funcionar para todas las entradas.
Actualización Consulte los formatos numéricos estándar . He tenido que establecer explícitamente el especificador de precisión en 29, ya que los documentos indican claramente:
Actualización Konrad señaló en los comentarios:
fuente
Me encontré con el mismo problema, pero en un caso en el que no tengo control de la salida a la cadena, que fue atendida por una biblioteca. Después de buscar detalles en la implementación del tipo Decimal (ver http://msdn.microsoft.com/en-us/library/system.decimal.getbits.aspx ), se me ocurrió un buen truco (aquí como una extensión método):
La parte exponente del decimal se reduce a lo que se necesita. Llamar a ToString () en el decimal de salida escribirá el número sin ningún 0 final. Por ejemplo
fuente
1
seguidas por 330
-s, pero eso crea exactamente la mismadecimal
instancia que un número con 29 cifras, una1
y 280
-s. Justo como dijo @ThomasMaterna en su comentario. NoSystem.Decimal
puede tener más de 29 cifras (los números con dígitos iniciales mayores que79228...
solo pueden tener 28 cifras en total) Si desea más ceros al final, multiplique por en1.000...m
lugar de dividir. Además,Math.Round
puede cortar algunos ceros, por ejemplo ,Math.Round(27.40000m, 2)
da27.40m
, por lo que solo queda un cero.En mi opinión, es más seguro usar cadenas de formato numérico personalizado .
fuente
Uso este código para evitar la notación científica "G29":
EDITAR: utilizando el sistema CultureInfo.NumberFormat.NumberDecimalSeparator:
fuente
Culture.NumberFormat.NumberDecimalSeparator
Use el
#
símbolo hash ( ) para mostrar solo los ceros finales cuando sea necesario. Ver las pruebas a continuación.fuente
num1.ToString("0.##")
debería devolver13.1534545765
(sin cambios) porque no hay ceros finales.Encontré una solución elegante en http://dobrzanski.net/2009/05/14/c-decimaltostring-and-how-to-get-rid-of-trailing-zeros/
Básicamente
fuente
v
es así0m
, el resultado de su código es una cadena vacía en lugar de"0"
.Un enfoque de muy bajo nivel, pero creo que esta sería la forma más eficaz utilizando solo cálculos enteros rápidos (y sin métodos lentos de análisis de cadenas y sensibles a la cultura):
fuente
a
yb
) en cada iteración mientras todos son cero de todos modos. Sin embargo, encontré esta solución sorprendentemente simple que también supera fácilmente lo que tú y yo hemos logrado con respecto al rendimiento .Esto funcionará:
O si su valor inicial es
string
:Presta atención a este comentario .
fuente
double.ToString
elimina los ceros finales de forma predeterminada.Esto es simple.
Probado
Salud :)
fuente
Depende de lo que represente su número y de cómo desee administrar los valores: ¿es una moneda, necesita redondeo o truncamiento, necesita este redondeo solo para mostrar?
Si para visualización, considere formatear los números son x.ToString ("")
http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx y
http://msdn.microsoft.com/en-us/library/0c899ak8.aspx
Si solo se trata de redondeo, use Math.Round overload que requiere una sobrecarga MidPointRounding
http://msdn.microsoft.com/en-us/library/ms131274.aspx )
Si obtiene su valor de una base de datos, considere la conversión en lugar de la conversión: valor doble = (decimal) myRecord ["columnName"];
fuente
Solo puede establecer como:
fuente
En caso de que desee mantener el número decimal, intente el siguiente ejemplo:
fuente
Intentando hacer una solución más amigable de DecimalToString ( https://stackoverflow.com/a/34486763/3852139 ):
Salida:
fuente
Realicé los siguientes métodos de extensión para mí para adaptarme a uno de mis proyectos, pero tal vez sean beneficiosos para otra persona.
Aunque requerirá una referencia a
System.Numerics
.fuente
La respuesta muy simple es usar TrimEnd (). Aquí está el resultado,
La salida es 1 Si mi valor es 1.01, entonces mi salida será 1.01
fuente
value = 100
?El siguiente código podría usarse para no usar el tipo de cadena:
Devuelve 789.5
fuente
Truncar los ceros finales es muy fácil, resuelva con una conversión dúplex:
(I) -> Analiza el valor decimal de cualquier fuente de cadena.
(II) -> Primero: Cast para duplicar esto, eliminar los ceros finales. Segundo: Otro conversión a decimal porque no existe conversión implícita de decimal a doble y viceversa)
fuente
prueba este código:
fuente
intenta así
y luego convertir eso para flotar
fuente
subString()
método para eso, pero de acuerdo con la pregunta publicada aquí, no veo ningún requisito como ese =)"12300.00"
que se recortará un examen"123"
. Otro efecto que parece indeseable es que algunos números, como los que"0.00"
se recortan hasta la cadena vacía""
(aunque este número es un caso especial de ser un "múltiplo de 10.0" integral).