Autor Tema: Contar cantidad de dígitos a la derecha de la coma [lenguajeC] hallar decimales  (Leído 24838 veces)

Pino06-01-2016

  • Sin experiencia
  • *
  • Mensajes: 7
    • Ver Perfil
Hola. El programa que muestro a continuación lo que hace es separar los dígitos que se encuentran a la izquierda de la coma y los que se encuentran a la derecha, o sea, la parte entera y la parte fraccionaria de una variable double, hasta hay todo bien, el error lo tengo cuando el bucle for no coincide con la cantidad de dígitos fraccionarios.-
Alguien me puede decir si es posible establecer cuantos dígitos ha ingresado el operador a la derecha de la coma, he intentado por todos los medios a mi alcance (lectura y búsqueda en la web) y no pude lograrlo.-

Código: [Seleccionar]
#include <stdio.h>
#include <float.h>

int main( void ){
double numero , decimal;
int entero, x = 1, ok, ch;

do{
printf("\n Ingrese un numero con decimales...: ");
ok = scanf( "%lf", &numero ) == 1 && numero > 0.00 && numero <= DBL_MAX;
while ((ch = getchar()) != EOF && ch != '\n');
}while(!ok);
 
entero = (int)numero;
decimal = numero - entero;

while(x <= 4 ){
decimal  *=10;
x++;
}
 
printf("\n La parte fraccionaria..:%g\n", decimal);
 
return 0;
}

Gracias y saludos.
« Última modificación: 17 de Enero 2016, 20:10 por Ogramar »

Ogramar

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 2660
    • Ver Perfil
Hola Pino no sé si esta idea te puede servir (tomada de http://aprenderaprogramar.com/index.php?option=com_content&view=article&id=941:ejercicios-codificacion-c-dibujar-rombo-diamante-arreglos-unidimensionales-calcular-sumatorios-cu00542f&catid=82:curso-basico-programacion-lenguaje-c-desde-cero&Itemid=210)

Para limitar el número de decimales utilizado se puede introducir un número junto al indicador de tipo de dato

Por ejemplo scanf( "%.2lf", &numero ) haría que se tomaran dos valores decimales

Se ha introducido .n (por ejemplo .2) después del símbolo % para indicar que se tomen n decimales

Otro ejemplo sería:

printf ("El precio del libro con isbn %.0lf es de %.2lf euros ", isbn, precio);

El primer número no mostraría decimales y el segundo mostraría dos decimales

Salu2

Pino06-01-2016

  • Sin experiencia
  • *
  • Mensajes: 7
    • Ver Perfil
Hola.
Gracias por ocuparte, el caso es un tanto sencillo, te pongo un ejemplo, se ingresa por teclado 123.456 para extraer la parte entera y la parte decimal utilizo estas 2 lineas de código:

Código: [Seleccionar]
entero = (int)numero;
decimal = numero - entero;

El resultado de la parte fraccionaria (que es la que no puedo resolver) es 0.456, para llegar a obtener tan solo 456 o sea sin parte fraccionaria como si fuera un entero debo saber de antemano por cuanto tengo que multiplicarlo en este caso x 1.000.-

12.3 la parte fraccionaria multiplicada x 10 es igual a 3   
12.34 la parte fraccionaria multiplicada x 100 es igual a 34   
12.345 la parte fraccionaria multiplicada x 1000 es igual a 345

Te voy a ser muy franco, ya estoy por tirar la toalla, hace una semana que estoy con el tema y parece que no tiene manera de lograrse.-

Ojalá Dios te ilumine y puedas ayudarme.-

Nota: recordar que no puedo utilizar el tipo char.- 

Saludos.
« Última modificación: 12 de Enero 2016, 13:09 por Pino06-01-2016 »

Ogramar

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 2660
    • Ver Perfil
Buenas, pues parece un problema sencillo pero no lo es, en parte por la forma de representación interna numérica que usan los computadores ya que lo que vemos en pantalla no es lo que usa el computador internamente.

La idea que podrías usar es partir de lo que tú has indicado como vía para obtener la parte fraccionaria, y luego irla reduciendo hasta que puedas determinar que has contabilizado todos los dígitos decimales. Es decir, tomar la parte entera haciendo un redondeo y luego multiplicar por 10, así hasta que llegues a cero:

Por ejemplo partimos de un número cuya parte decimal sea .2155 y multiplicamos por 10

.2155 * 10 = 2.155 le restamos la parte entera y nos queda .155 (contador: un decimal)
.155 * 10 = 1.55 le restamos la parte entera y nos queda .55 (contador: dos decimales)
.55 * 10 = 5.5 le restamos la parte entera y nos queda .5 (contador: tres decimales)
.5 * 10 = 5.0 le restamos la parte entera y nos queda cero (contador: cuatro decimales)

4 multiplicaciones por diez hasta llegar a cero, serían 4 decimales

Expresado ya con la idea de código sería algo como esto:

Código: [Seleccionar]
count = 0
num = abs(num)
num = num - int(num)
while num != 0:
    num = num * 10
    count = count + 1
    num = num - int(num)

No lo he probado pero parece que podría funcionar tanto para contar el número de decimales como para saber cuáles son esos decimales

Salu2

Pino06-01-2016

  • Sin experiencia
  • *
  • Mensajes: 7
    • Ver Perfil
Hola, Ogramar.
Créeme que ya me canse de practicar y no doy con el error, te dejo el código por si quieres revisarlo y una captura ingresando el número que propusiste.- 



Código: [Seleccionar]
#include <stdio.h>
#include <float.h>
#include <stdlib.h>

int main( void ){
double numero , decimal;
int entero, contador = 0, ok, ch;

do{
printf("\n Ingrese un numero con decimales...: ");
ok = scanf( "%lf", &numero ) == 1 && numero > 0.00 && numero <= DBL_MAX;
while ((ch = getchar()) != EOF && ch != '\n');
}while(!ok);
 
entero = (int)numero;
decimal = numero - entero;

while(decimal != 0 ){
decimal = decimal * 10;
decimal = decimal - (int)decimal;
printf("\n Decimal...: %g", decimal);
// getchar();
contador ++;
}
 
printf("\n Total de digitos despues de la coma..:%d\n", contador);
 
return 0;
}

Saludos.

Ogramar

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 2660
    • Ver Perfil
Buenas Pino, he hecho pruebas y pienso que el problema está en la precisión decimal y en la forma interna (con base 2) de manejo de números por parte del lenguaje.

Si introduzco 5.25 obtengo esto:


Ingrese un numero con decimales...: 5.25
El entero es 5
El decimal es 0.250000
Por 10 hemos obtenido 2.500000
La parte entera es 2

 Tras restar parte entera hemos obtenido Decimal...: 0.500000
Por 10 hemos obtenido 5.000000
La parte entera es 5

 Tras restar parte entera hemos obtenido Decimal...: 0.000000
 Total de digitos despues de la coma..:2


Si introduzco 5.22 obtengo esto:


Ingrese un numero con decimales...: 5.22
El entero es 5
El decimal es 0.220000
Por 10 hemos obtenido 2.200000
La parte entera es 2
Tras restar parte entera hemos obtenido Decimal...: 0.200000
Por 10 hemos obtenido 2.000000
La parte entera es 1


Aquí ya vemos cómo ha fallado. Nos está diciendo que la parte entera de 2 es 1 ¿Por qué? Porque la representación interna que utiliza el computador quizá le lleve a tomar otro valor en lugar de 2, y nos dice que la parte entera es 1.

Supongo que dándole vueltas se podrá resolver, pero no es sencillo...

Salu2

Pino06-01-2016

  • Sin experiencia
  • *
  • Mensajes: 7
    • Ver Perfil
Hola, Ogramar.
Muchas gracias por todo lo que hiciste para que funcione, no te ocupes más de este asunto, tal vez cuando lo olvides, te caiga la ficha, yo voy a seguir intentando, no me cabe que la fórmula que propusiste no funcione. -

Un fuerte abrazo.

Ogramar

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 2660
    • Ver Perfil
Buenas Pino, he vuelto a mirarlo pero no encuentro demasiada inspiración; sigo encontrando el problema de la representación interna del número que usa el computador.

El asunto deriva de la representación binaria de números decimales. Algunos números tienen una representació exacta, pero otros son solo aproximaciones. Si almacenamos por ejemplo 3.44 en un double, el valor real almacenado en el sistema puede ser 3.439999999999999946709294817992486059665679931640625, que tiene 51 posiciones dígitos en su parte decimal (aunque nosotros por pantalla veamos 3.44). Para C 3.44 y 3.439999999999999946709294817992486059665679931640625 vienen siendo el mismo número, de ahí la dificultad de poder decir cuántos decimales tiene. Si el número que internamente guarda el computador es 3.439999999999999946709294817992486059665679931640625 ¿Por qué íbamos a ser capaces de decir que tiene 2 decimales? (Realmente en la representación interna no los tiene).

Podría tratar de detectarse a qué valor está próximo el número, pero eso también es complejo sobre todo porque no estaría claro a qué número se debe aproximar un número con 51 dígitos decimales.

Una aproximación a resolver el problema sería basarse en convertirlo a string, extraer los tokens, hacer el conteo y devolver el número de decimales

Código: [Seleccionar]
#include <stdio.h>
#include <string.h>

/* Counting the number of decimals
 *
 * 1. Use Scientific Notation format
 * 2. Convert it to a string
 * 3. Tokenize it on the exp sign, discard the base part
 * 4. convert the second token back to number
*/

int main(){

   int counts;
   char *sign;
   char str[15];
   char *base;
   char *exp10;
   float real = 0.00001;

   sprintf (str, "%E",  real);
   sign= ( strpbrk ( str, "+"))? "+" : "-";

   base = strtok (str, sign);
   exp10 = strtok (NULL, sign);

   counts=atoi(exp10);

   printf("[%d]\n", counts);

   return 0;
}


Salu2

 

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".