Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: NOB2014 en 9 Enero 2016, 15:34 pm



Título: [Solucionado] Establecer la cantidad de dígitos a la derecha de la coma [C]
Publicado por: NOB2014 en 9 Enero 2016, 15:34 pm
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
  1. #include <stdio.h>
  2. #include <float.h>
  3.  
  4. int main( void ){
  5. double numero , decimal;
  6. int entero, x = 1, ok, ch;
  7.  
  8. do{
  9. printf("\n Ingrese un numero con decimales...: ");
  10. ok = scanf( "%lf", &numero ) == 1 && numero > 0.00 && numero <= DBL_MAX;
  11. while ((ch = getchar()) != EOF && ch != '\n');
  12. }while(!ok);
  13.  
  14. entero = (int)numero;
  15. decimal = numero - entero;
  16.  
  17. while(x <= 4 ){
  18. decimal  *=10;
  19. x++;
  20. }
  21.  
  22. printf("\n La parte fraccionaria..:%g\n", decimal);
  23.  
  24. return 0;
  25. }

Desde ya muchas gracias
Saludos


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: MAFUS en 9 Enero 2016, 16:36 pm
Hace no mucho se ha tratado este tema en el foro
http://foro.elhacker.net/programacion_cc/super_solucionado_separar_parte_decimal_y_parte_fraccionaria_en_lenguaje_c-t446426.0.html


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: NOB2014 en 9 Enero 2016, 16:49 pm
Hola MAFUS.
Debo suponer que estabas apurado (¿...?), ese post lo di de alta yo y además son cosas distintas, caso contrario lo ubiera continuado.-

Saludos.


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: ivancea96 en 9 Enero 2016, 17:04 pm
Citar
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

Qué bucle for. Qué operador.


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: NOB2014 en 9 Enero 2016, 17:11 pm
Mil disculpas, el bucle es while y el operador es el que tipea el teclado.-


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: MAFUS en 9 Enero 2016, 17:29 pm
Lo puedes hacer de otra forma: pilla el número como una cadena de caracteres. Usa las ventajas de trabajar con cadenas para conseguir saber cuántos caracteres hay detrás de la coma. Después transforma esa cadena en un double con strtod si necesitas el valor numérico.


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: NOB2014 en 9 Enero 2016, 17:47 pm
Hola
Lo que sucede es que el manual de donde saque el ejercicio dice que utilice el tipo float, en realidad tube que hacerlo con double porque si se ingresa por Ej. 123.045 el cero inmediatamente después de la coma hace que el resultado sea incorrecto (solo en este caso, cero después de la coma), no dice que se pueda hacer con cadena.-
Tal vez lo que estoy pidiendo no se pueda, caso contrario vos o ivancea92 ya lo hubieran descubierto.-

Saludos y gracia por ocuparse.


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: ivancea96 en 9 Enero 2016, 17:57 pm
Si lo que queires es saber el número de dígitos decimales de un número, te pongo 2 opciones. La priemra, la que dijo MAFUS, leerlo como cadena, comprobar los dígitos, y ya luego convertirlo a float;
Otra solución, puede ser algo del estilo de:

Código
  1. float n = 456.789;
  2. int digitos = 0;
  3. while( (float)(int)n != n){
  4.    digitos += 1;
  5.    n *= 10;
  6. }

Si quieres lograr otra cosa, explícalo mejor.


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: MAFUS en 9 Enero 2016, 18:35 pm
Lo malo de los reales en computación que siguen el IEEE 754, como en caso de C, C++, etc. es que cuándo se pasan a entero pierden precisión. El caso presentado por ivancea96 es uno de ellos. Así da como resultado 5 dígitos decimales.


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: NOB2014 en 9 Enero 2016, 20:15 pm
Hola.
ivancea96 es eso precisamente lo que quiero lograr, saber la cantidad de dígitos que hay después de la coma y lo que dice MAFUS es correcto (resultado = 5 dígitos).-
Me cuesta creer que haya algo que en C no se pueda hacer, seguiremos intentando, no me voy a dar por vencido tan pronto.-     

Saludos.


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: ivancea96 en 9 Enero 2016, 21:01 pm
Me cuesta creer que haya algo que en C no se pueda hacer, seguiremos intentando, no me voy a dar por vencido tan pronto.
Desde luego se puede lograr. Como biens e ha dicho, la coma flotante trabaja con binario, y hay números contados que van a dar un resultado preciso. Si loq ue queires es saber lso decimales que tendrá un número introducido por el usuario, como bien has dicho, lee lo que el usuario ha introducido. scanf transforma cadenas a los tipso que le pongas.


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: NOB2014 en 10 Enero 2016, 16:05 pm
Hola.
Bueno el obsesivo Daniel sigue practicando, les dejo lo que cambie dentro del bucle, lo que muestra printf no se refleja en el bucle, al ser iguales las 2 cifras ¿por qué no sale del mismo? o lo que muestra printf no es real o exacto. -

Código
  1. while(x <= 6 ){
  2. decimal *=10;
  3. x++;
  4. temp = decimal + 1e-9;
  5. if( temp == decimal ) {break;}
  6. printf("\n decimal = %g ==> temp = %d", decimal, temp);
  7. }
  8.  

(http://i64.tinypic.com/200fzb9.png)

Saludos.


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: ivancea96 en 10 Enero 2016, 16:50 pm
Cuandpo a una variable flotante le sumas un flotante mucho menor, no se va a cambiar.
Para que lo veas con otro ejemplo, si a 10^1000 le sumas 1, va a seguir siendo 10^1000.


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: MAFUS en 10 Enero 2016, 18:25 pm
Si vas a buscar una fórmula matemática para conseguir los números, en base 10, que han escrito detrás de la coma te digo que conseguirías un hito. Para ello tienes dos vídeos que están relacionados.

Éste primero muestra como convertir un binario real a un decimal real:
https://www.youtube.com/watch?v=PtX_nWKMOxw

Y éste segundo muestra como convertir un real binario en su representación IEEE 754:
https://www.youtube.com/watch?v=VlX4OlKvzAk

Como puedes ver saber cuántos números decimales hay después de una coma en un real decimal es harto complicado.

Te será más fácil si lo haces en base a caracteres, como se ha mencionado anteriormente.


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: NOB2014 en 10 Enero 2016, 21:58 pm
Hola MAFUS.
Me parece genial la idea, de echo es lo primero que pense para hacer que el programa logre el cometido pero luego recordé que las operaciones a nivel de bist se pueden aplicar únicamente a variables enteras, pero mirando el video se me antojo que lo puedo intentar con desplazamiento de bits, siempre utilizo el ampersand(&) para hacer este tipo de prácticas, el programa que dejo a continuación es una muestra de ello.-

Código
  1. #include<stdio.h>
  2.  
  3. int main( void ){
  4. int numero = 1854, i, b = 1, temp = 0, x;
  5.  
  6. for( i = 0; i < 32; i++ ){
  7. temp += numero & b;
  8. x = numero & b;
  9. if( x > 0 ) printf("\n bit encendido ==> [%d] = %d", i, x);
  10. b *= 2;
  11. }
  12.  
  13. printf( "\n\n La direccion de memoria %p contiene el valor %d\n\n", &numero, temp );
  14.  
  15. return 0;
  16. }

gracias ivancea96 por la aclaración.-   
A seguir intentando.
Saludos


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: MAFUS en 10 Enero 2016, 22:37 pm
El manejo de bits es muy poderoso.

Un aporte:
Cuándo hagas el desplazamiento de bits, cómo haces en b *= 2; escríbelo como b <<= 1. Los desplazamientos de bits son más rápidos que las multiplicaciones. Ídem para las divisiones.


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: NOB2014 en 13 Enero 2016, 18:16 pm
Hola a todos.
0xFer, mil disculpas por no prestar demasiada atención a lo que proponías en este post:http://foro.elhacker.net/programacion_cc/super_solucionado_separar_parte_decimal_y_parte_fraccionaria_en_lenguaje_c-t446426.0.html si bien es efectivo cuando la variable se inicializa a mano no sirve cuando la misma se le aplica el valor por teclado, no sirve porque aparentemente no se puede establecer cuantos decimales tiene un tipo de coma flotante, pero como Danielito es un tanto obsesivo sigue intentando.-
Lo que traigo ahora es la siguiente formula que en un papel y con la calculadora funciona, pero en el ordenador da resultado erróneo, yo quiero creer en una frase que me dijo un conocido (mío) exprogramador: Todo lo que puedas hacer con un lápiz y un papel yo lo puedo hacer con el ordenador.-

Un Ej. con el número .2155
.2155 * 10 = 2.155 le restamos la parte entera y nos queda .155 (1 decimal)
.155 * 10 = 1.55 le restamos la parte entera y nos queda .55 (2 decimales)
.55 * 10 = 5.5 le restamos la parte entera y nos queda .5 (3 decimales)
.5 * 10 = 5.0 le restamos la parte entera y nos queda cero (4 decimales)

El resultado es infalible, en el papel, pero en el programa que dejo a continuación no.- 

Código
  1. #include <stdio.h>
  2. #include <float.h>
  3.  
  4. int main( void ){
  5. double numero , decimal;
  6. int entero, contador = 0, ok, ch;
  7.  
  8. do{
  9. printf("\n Ingrese un numero con decimales...: ");
  10. ok = scanf( "%lf", &numero ) == 1 && numero > 0.00 && numero <= DBL_MAX;
  11. while ((ch = getchar()) != EOF && ch != '\n');
  12. }while(!ok);
  13.  
  14. entero = (int)numero;
  15. decimal = numero - entero;
  16.  
  17. while(decimal != 0 ){
  18. decimal = decimal * 10;
  19. decimal = decimal - (int)decimal;
  20. printf("\n Decimal...: %g", decimal);
  21. contador ++;
  22. }
  23.  
  24. printf("\n Total de digitos despues de la coma..:%d\n", contador);
  25.  
  26. return 0;
  27. }

(http://i68.tinypic.com/2ahha10.png)

(http://i63.tinypic.com/vfkgy.png)

Si todavía alguien desea decirme el porqué, muy pero muy agradecido.-

Saludos.


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: MAFUS en 13 Enero 2016, 18:43 pm
Sigue siendo más de lo mismo. Tu trabajas en decimal, el ordenador no. El ordenador trabaja en números binarios en coma flotante, y no solo eso: trabaja con una forma especial para que fue diseñada para que equipos de computación trabajen con números binarios, el IEEE 754.


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: Yoel Alejandro en 18 Enero 2016, 18:39 pm
Bueno, .... está muy interesante el tema!

El problema parece ser que el redondeo a entero de un número teóricamente entero, no es necesariamente un "entero" desde el punto de vista de la máquina.
Entonces cuando multiplicamos por 10, nunca llegamos a obtener un "entero" desde el punto de vista de la máquina.

Probé a hacer lo siguiente, incluir la biblioteca <math.h>, y mandar a imprimir en cada ciclo la diferencia entre el número actual, y el redondeo del mismo. Lo imprimimos en notación científica para apreciar mejor el orden de magnitud del número
Código
  1. while( contador < 20 && fabs(numero - round(numero)) != 0 ) {
  2.        contador++;
  3. numero *= 10;
  4. printf("Numero es ...: %lf, van: %d decimales\n", numero, contador );
  5. printf("  Diferencia: %.2E\n", fabs(numero - round(numero)));
  6. }
  7.  
(donde la condición del contador menor a 20 es para prevenir ciclo infinito). El resultado será

 Ingrese un numero con decimales...: .2155
1.19E-07
Numero es ...: 2.155000, van: 1 decimales
  Diferencia: 1.55E-01
Numero es ...: 21.550000, van: 2 decimales
  Diferencia: 4.50E-01
Numero es ...: 215.500000, van: 3 decimales
  Diferencia: 5.00E-01
Numero es ...: 2155.000000, van: 4 decimales
  Diferencia: 4.55E-13
Numero es ...: 21550.000000, van: 5 decimales
  Diferencia: 3.64E-12
Numero es ...: 215500.000000, van: 6 decimales
  Diferencia: 2.91E-11
Numero es ...: 2155000.000000, van: 7 decimales
  Diferencia: 4.66E-10
Numero es ...: 21550000.000000, van: 8 decimales
  Diferencia: 3.73E-09
Numero es ...: 215500000.000000, van: 9 decimales
  Diferencia: 2.98E-08
Numero es ...: 2155000000.000000, van: 10 decimales
  Diferencia: 4.77E-07


Pero vemos que el algún momento la diferencia entre ambos es un número muy pequeño, teóricamente cero pero que en la práctica no es cero. Debe ser un número menor al épsilon de la máquina, el cual desde el punto de vista teórico debemos tomaralo como un cero. Por lo tanto detenemos el ciclo cuando la diferencia entre el número y su redondeo sea menor a dicho épsilon:
Código
  1. while( contador < 20 && fabs(numero - round(numero)) > FLT_EPSILON ) {
  2.    contador++;
  3.    numero *= 10;
  4.    printf("Numero es ...: %lf, van: %d decimales\n", numero, contador );
  5.    printf("  Diferencia: %.2E\n", fabs(numero - round(numero)));
  6. }
  7. }

Con lo cual se obtiene lo esperado

 Ingrese un numero con decimales...: .2155
1.19E-07
Numero es ...: 2.155000, van: 1 decimales
  Diferencia: 1.55E-01
Numero es ...: 21.550000, van: 2 decimales
  Diferencia: 4.50E-01
Numero es ...: 215.500000, van: 3 decimales
  Diferencia: 5.00E-01
Numero es ...: 2155.000000, van: 4 decimales
  Diferencia: 4.55E-13

 Total de digitos despues de la coma..:4


De todos modos, creo que lo más seguro en estos casos sigue siendo recibir el número como cadena, y convertirlo internamente a número según un algoritmo implementado directamente por nosotros. Creo que así debe ser la manera como trabajan los intérpretes de comandos como cmd, o bash

Un saludo, Yoel
Puedes enviarme un M.P.



Por cierto, respondiendo este post tuve que editar el mensaje como 10 veces, recortarlo, editarlo por partes, etc ....

El servicio anti-DOS me enviaba una alerta de "Attention Required", como que supuestamente estaba intentando invadir el foro con Scripting Injection. Lo cual es totalmente falso, entonces no se por qué el anti-DOS me rebotaba a cada rato. A lo mejor estaba malinterpretando como nocivas las etiquetas "code", o "tt"


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: Eternal Idol en 18 Enero 2016, 18:52 pm
Por cierto, respondiendo este post tuve que editar el mensaje como 10 veces, recortarlo, editarlo por partes, etc ....

El servicio anti-DOS me enviaba una alerta de "Attention Required", como que supuestamente estaba intentando invadir el foro con Scripting Injection. Lo cual es totalmente falso, entonces no se por qué el anti-DOS me rebotaba a cada rato. A lo mejor estaba malinterpretando como nocivas las etiquetas "code", o "tt"

Crea un hilo en: https://foro.elhacker.net/sugerencias_y_dudas_sobre_el_foro-b10.0/


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: kondrag_X1 en 18 Enero 2016, 19:12 pm
Siento mucho decirte que si te quieres complicar vas a tener que trabajar a nivel de bit con el estándar IE754, no es complicado separas parte entera mantisa y exponente y sacas los datos.


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: NOB2014 en 19 Enero 2016, 00:48 am
Hola, Yoel Alejandro. -
Estebe haciendo muchas pruebas y el resultado es siempre correcto, solo falla cuando introduzco más de 9 dígitos a la derecha de la coma, pero eso no es inpedimento y en todo caso se puede limitar. -
kondrag_X1 voy a informarme sobre lo que propones porque me quede muy intrigado, no sé por dónde empezar. -

Saludos.


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: Yoel Alejandro en 19 Enero 2016, 14:05 pm
NOB2014, puedes aumentar la precisión cambiando en donde dice FLT_EPSILON por la constante DBL_EPSILON

En este caso cambias del épsilon de la máquina para punto flotante al épsilon para precisión doble. Creo que al manejar más de nueve decimales estás considerando una precisión doble, por eso requieres DBL_EPSILON

Saludos, Yoel


Título: Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C]
Publicado por: NOB2014 en 19 Enero 2016, 14:27 pm
Hola, Yoel.
Maravilloso, posibilita un máximo de 14 dígitos, más que suficiente. -

Saludos.
Daniel


Título: Re: [Solucionado] Establecer la cantidad de dígitos a la derecha de la coma [C]
Publicado por: furciorifa en 30 Enero 2016, 23:15 pm
Por fin he solucionado lo que querías amigo y sí hay una forma estándar y sencilla de hacerlo te paso mi código y espero que te guste sigue las instrucciones, te pido por favor que me envies un mensaje si te funciono es para cuestiones estadísticas que llevo
Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3.  
  4. int main()
  5. {
  6.   div_t d;
  7.   int num, denom;
  8.   double aux;
  9.   printf( "Escriba el numerador y el denominador (separados por un espacio):\n" );
  10.   scanf( "%d %d", &num, &denom );
  11.   d = div( num, denom );
  12.    aux=d.rem/(double)denom;
  13.   printf( "ldiv( %d, %d ) : cociente = %d, resto = %f\n", num, denom, d.quot, aux );
  14.  
  15.   return 0;
  16. }
(http://i.imgur.com/iPrzfkG.png)
Espero que me contestes



Esta solución permite 30 decimales !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) :silbar: :silbar: :silbar:


Código
  1.  
  2.  
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5.  
  6. int main()
  7. {
  8.   div_t d;
  9.   int num, denom;
  10.   double aux;
  11.   printf( "Escriba el numerador y el denominador (separados por un espacio):\n" );
  12.   scanf( "%d %d", &num, &denom );
  13.   d = div( num, denom );
  14.    aux=d.rem/(double)denom;
  15.   printf( "ldiv( %d, %d ) : cociente = %d, resto = %.30lf\n", num, denom, d.quot, aux );
  16.  
  17.   return 0;
  18. }
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  
(http://i.imgur.com/XlBEHeP.png)


Título: Re: [Solucionado] Establecer la cantidad de dígitos a la derecha de la coma [C]
Publicado por: ivancea96 en 30 Enero 2016, 23:54 pm
De esos decimales, solo 15 son reales.


Título: Re: [Solucionado] Establecer la cantidad de dígitos a la derecha de la coma [C]
Publicado por: furciorifa en 31 Enero 2016, 04:39 am
De esos decimales, solo 15 son reales.
Así es jeje no me fije, pero ya con una variable más grande tiene más precisión, un long double, me parece, de cualquier forma creo que mi solución es la que parece más eficaz no sé qué le parezca al dueño del post.