2010-07-19 22 views
8

Tenemos un problema interesante si necesitamos determinar la precisión decimal de la entrada de un usuario (cuadro de texto). Esencialmente lo que necesitamos saber el número de decimales introducidos y devolver un número de precisión, esto se ilustra mejor con ejemplos:Determine la precisión decimal de un número de entrada

4500 entraron producirá un resultado 1
4.500,1 entraron producirá un resultado 0,1
4500.00 introducido se produce un resultado 0.01
4500.450 ingresado dará un resultado 0.001

Estamos pensando en trabajar con la cadena, encontrar el separador decimal y luego calcular el resultado. Me pregunto si hay una solución más fácil para esto.

+3

¿Estás seguro de que 4500 sería un 1, y no un 100? – corsiKa

+0

¿Cuál es el resultado esperado en el caso 0.0 y 0.1? – user1785960

+0

Para mí es una pregunta confusa. No pides precisión decimal. Usted pregunta: cómo obtener el número de dígitos en una parte de la fracción. La definición de 'precisión decimal' está aquí para Mí: https://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm#i16209 – user1785960

Respuesta

8

Dado que los últimos ejemplos indican que los ceros finales son significativos, descartaría cualquier solución numérica y recurriré a las operaciones de cadena.

3

No, no hay una solución más fácil, debe examinar la cadena. Si convierte "4500" y "4500.00" en números, ambos se convierten en el valor 4500, por lo que no puede decir cuántos dígitos sin valor había detrás del separador decimal.

1

Trabajar con la cuerda es bastante fácil.

Si no hay "." en la cadena, return 1.

Else devuelve "0.", seguido de n-1 "0", seguido de un "1", donde n es la longitud de la cadena después del punto decimal.

+0

Advertencia: Primero asegúrese de que la cadena sea un número válido/el el último personaje no es un "." – luiscubal

9

Solo me pregunta si hay una solución más fácil para esto.

Usar cadena:

string[] res = inputstring.Split('.'); 
int precision = res[1].Length; 
+15

El carácter para dividir debe ser el separador decimal correcto - [NumberFormatInfo.NumberDecimalSeparator] (http://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo.numberdecimalseparator.aspx) – ChrisF

14

creo que sólo debe hacer lo que usted sugiere - utilizar la posición del punto decimal. Obvio inconveniente podría ser que usted tiene que pensar en la internacionalización usted mismo.

var decimalSeparator = NumberFormatInfo.CurrentInfo.CurrencyDecimalSeparator; 

var position = input.IndexOf(decimalSeparator); 

var precision = (position == -1) ? 0 : input.Length - position - 1; 

// This may be quite unprecise. 
var result = Math.Pow(0.1, precision); 

Hay otra cosa que podría intentar - los Decimal tipo almacena un valor precission interna. Por lo tanto, puede usar Deciml.TryParse() e inspeccionar el valor devuelto. Quizás el algoritmo de análisis mantenga la precisión de la entrada.

Finalmente, le sugiero que no intente algo usando números de coma flotante. Solo al analizar la entrada se eliminará cualquier información sobre los ceros al final. Por lo tanto, debe agregar un dígito artificial distinto de cero para conservarlos o hacer trucos similares. Es posible que se encuentre con problemas de precisión. Finalmente, encontrar la precisión basada en un número de coma flotante no es simple también. Veo algunas matemáticas feas o un ciclo que se multiplica con diez en cada iteración hasta que ya no hay ninguna parte fraccionaria. Y el bucle viene con nuevas emisiones de Precisión ...

ACTUALIZACIÓN

Analizar en unas obras deciaml. Se Decimal.GetBits() para más detalles.

var input = "123.4560"; 

var number = Decimal.Parse(input); 

// Will be 4. 
var precision = (Decimal.GetBits(number)[3] >> 16) & 0x000000FF; 

Desde aquí usando Math.Pow(0.1, precision) es sencillo.

+0

+1 Para decimal.Precision, no tenía idea de que podría hacer esto :) Ver http://stackoverflow.com/questions/1132765/adjusting-decimal-precision-net –

+1

Dado que el OP pidió "una solución más fácil", y tal vez inferir " mejor rendimiento ", ¿cómo se compara esto en términos de rendimiento con solo analizar la cadena? –

+0

¡Gracias por esto! –

2

Como un aspecto interesante, el Decimal intenta mantener la precisión introducida por el usuario. Por ejemplo,

Console.WriteLine(5.0m); 
Console.WriteLine(5.00m); 
Console.WriteLine(Decimal.Parse("5.0")); 
Console.WriteLine(Decimal.Parse("5.00")); 

tiene una salida de:

5.0 
5.00 
5.0 
5.00 

Si su motivación en el seguimiento de la precisión de la entrada es puramente por razones de entrada y salida, esto puede ser suficiente para hacer frente a su problema.

+0

Consulte la respuesta de Daniel Bruckner sobre cómo acceder a esta información directamente. – Brian

1

Aquí hay una posible solución con cadenas;

static double GetPrecision(string s) 
{ 
    string[] splitNumber = s.Split('.'); 
    if (splitNumber.Length > 1) 
    { 
     return 1/Math.Pow(10, splitNumber[1].Length); 
    } 
    else 
    { 
     return 1; 
    } 
} 

Hay una pregunta aquí; Calculate System.Decimal Precision and Scale que parece que podría ser de interés si desea profundizar en esto un poco más.

+1

Debe usar [NumberFormatInfo.NumberDecimalSeparator] (http://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo.numberdecimalseparator.aspx) para obtener el separador decimal correcto para la configuración regional. – ChrisF

+0

Genial, gracias por la sugerencia. –

Cuestiones relacionadas