2012-02-21 13 views
11

tengo un valor doble decimales:Encontrar el número de posiciones después del punto de un doble

double a = 4.5565; 

¿Cuál es la forma más fácil de calcular el número de dígitos después del punto decimal (4 en este caso).

Sé que puedo convertir a cadena y hacer una división y tomar la longitud. Pero, ¿hay una manera más fácil?

+0

¿Qué quiere decir por "más fácil"? Dudo que haya algo más fácil desde la perspectiva de la escritura/lectura, pero podría ser de alguna manera más fácil en términos de operaciones de CPU, por ejemplo. – Snowbear

+2

Esto no es posible en realidad. http: //en.wikipedia.org/wiki/Double-precision_floating-point_format – SLaks

+2

El valor de 'a' probablemente no sea exactamente 4.5565. Si no entiende por qué, le sugiero que lea esto: http://csharpindepth.com/Articles/General/FloatingPoint.aspx –

Respuesta

17

No hay una manera fácil, sobre todo porque el número de dígitos matemáticamente hablando podría ser mucho mayor que el que se muestra. Por ejemplo, 4.5565 se almacena actualmente como 4.556499999999999772626324556767940521240234375 (gracias a harold para calcular eso). Es muy poco probable que encuentre una solución útil a este problema.

EDITAR

Usted podría llegar a algún algoritmo que funciona así: si, como se calcula la representación decimal, a encontrar un cierto número de 9s (o ceros) seguidas, redonda arriba (o abajo) hasta el último lugar antes de que comience la serie de 9s (o ceros). Sospecho que encontrarías más problemas en ese camino de lo que anticipabas.

+0

@harold gracias, no tuve tiempo para resolverlo yo solo. – phoog

+0

@phoog Estoy de acuerdo con lo que dices en general, pero ¿qué opinas de mi respuesta? –

+0

@DorCohen No tengo tiempo ahora para ver tu respuesta en profundidad. Intentaré echar un vistazo más tarde esta noche o mañana por la mañana. – phoog

3

Creo solución de cuerdas es mejor: ((a-(int)a)+"").length-2

+0

en lugar de dividir, simplemente no cuenta '0.' en la cadena. No es muy diferente de la solución de blitzkriegz –

+0

@ L.B cierto, pero en mi solución no hay necesidad de asignar matriz. es un poco mejor – james

+4

Agregar "" es una alternativa realmente horrible a llamar a 'ToString()'. –

7
var precision = 0; 
var x = 1.345678901m; 

while (x*(decimal)Math.Pow(10,precision) != 
     Math.Round(x*(decimal)Math.Pow(10,precision))) 
    precision++; 

precision será igual al número de dígitos significativos del valor decimal (el servidor X a 1,23456000 dará lugar a una precisión de 5 a pesar de 8 dígitos eran originalmente especificado en el literal). Esto se ejecuta en el tiempo proporcional a la cantidad de decimales. Cuenta el número de dígitos fraccionarios SOLAMENTE; puede contar el número de lugares a la izquierda del punto decimal tomando la parte entera de Math.Log10 (x). Funciona mejor con decimales ya que tienen una mejor precisión de valor por lo que hay menos error de redondeo.

+0

Su solución es muy elegante, gracias –

3

escribir una función

int CountDigitsAfterDecimal(double value) 
     { 
      bool start = false; 
      int count = 0; 
      foreach (var s in value.ToString()) 
      { 
       if (s == '.') 
       { 
        start = true; 
       } 
       else if (start) 
       { 
        count++; 
       } 
      } 

      return count; 
     } 
-2

Hay un muy buen artículo que se encuentre en el foro STSdb: Number of digits after decimal point. En él se resumen muchas de las implementaciones conocidas - ToString(), potencias de 10 método y otros enfoques más avanzados. Se proporcionan pruebas de comparación, que muestran cuáles de los métodos son los más rápidos. Las soluciones proporcionadas funcionan para tipos dobles y decimales.

+2

El enlace está roto – berkeleybross

+0

La URL actual parece ser esta: http://stssoft.com/forum/threads/462-Number-of-digits-after-decimal-point Sin embargo, el los contenidos están bloqueados detrás de un muro de registro, por lo que no puedo verificar el contenido. –

+0

@Kris Con un enlace roto, su respuesta ya no es útil. Por favor arregle o elimine. –

0

tal vez voy a utilizar este código si necesitaba,

myDoubleNumber.ToString("R").Split('.')[1].Length 

"R" aquí es Round Trip Format Specifier

Necesitamos comprobar los límites de índice primero, por supuesto.

0

Creo que esto podría ser una solución:

private static int getDecimalCount(double val) 
{ 
    int i=0; 
    while (Math.Round(val, i) != val) 
     i++; 
    return i; 
} 

double val9 = 4.5565d; int count9 = getDecimalCount(val9);//result: 4 

Lo siento por la duplicación ->https://stackoverflow.com/a/35238462/1266873

Cuestiones relacionadas