2010-04-26 14 views
17

Me di cuenta de que .NET tiene un comportamiento funky/no intuitiva cuando se trata de decimales y ceros finales.Decimal - truncate ceros finales

0m == 0.000m //true 
0.1m == 0.1000m //true 

pero

(0m).ToString() == (0.000m).ToString() //false 
(0.1m).ToString() == (0.1000m).ToString() //false 

que sé acerca de la necesidad de cumplir con el estándar ECMA CLI. Sin embargo, me gustaría saber si hay una forma incorporada de truncar los ceros finales para un valor decimal sin pasar por la representación de cadena (.ToString ("G29") y el truco de analizar analizar funcionaría, pero no es una solución rápida ni elegante)?

¿Alguna idea? Muchas gracias.

+0

Hmmm ... estoy pensando en algo relacionado con 'decimal.GetBits' y la aritmética de 96 bits, pero no es sencillo. –

+1

Consulte http://stackoverflow.com/questions/1584314/ para obtener una pregunta relacionada. Una de las respuestas da el truco de dividir entre 1.000 ... 0000m para eliminar efectivamente los ceros finales (presumiblemente porque el exponente "ideal" para un cociente x/y es la diferencia de los exponentes de xey). Sin embargo, es sorprendente que no haya un método de "normalización". –

Respuesta

16

Creo que lo que necesita es este (más detalles en mi respuesta here):

public static decimal Normalize(decimal value) 
{ 
    return value/1.000000000000000000000000000000000m; 
} 
+0

Este es el más rápido que he encontrado y supera mis propios intentos de hacer giros binarios, aunque superan fácilmente a todos los otros contendientes aquí, incluso [este enfoque algo similar] (http://stackoverflow.com/a/20647024/709537) en una [pregunta duplicada] (http://stackoverflow.com/q/4525854/709537). –

7

utilizar una cadena de formato para especificar la salida de ToString():

(0.1m).ToString("0.#") -> "0.1" 
(0.10000m).ToString("0.#") -> "0.1" 

utilizar un "0" en el formato para especificar un dígito o un no significate 0, utilice "#" para especificar una dígito significativo o suprimir aa no significativo 0.

Editar: Asumiendo aquí que le preocupa la representación visual (cadena) del número - si no, eliminaré mi respuesta.

+1

No me importa mucho la representación visual. El problema es que cuando paso esos valores al motor de JScript, los valores de tipo de 1.0000 m lo desordenan por alguna razón. Sin embargo, la respuesta es la misma. PD 0.10000m.ToString ("G29") funciona para cualquier cantidad de dígitos significativos. – Konrad

+1

Esto también redondeará el valor, por ejemplo 123.4567 con 0. # aplicado se convierte en 123.5 – CRice

3

no me gusta mucho, pero funciona (por alguna rango de valores, por lo menos) ...

static decimal Normalize(decimal value) 
    { 
     long div = 1; 
     while(value - decimal.Truncate(value) != 0) 
     { 
      div *= 10; 
      value *= 10; 
     } 
     if(div != 1) { 
      value = (decimal)(long)value/div; 
     } 
     return value; 
    } 
+0

Funciona para la mayoría de los casos. Desafortunadamente no funciona para los tipos de valores 0.00000m. Necesitaría otro 'si' para verificar el cero decimal y esto lo haría aún más complicado. – Konrad

Cuestiones relacionadas