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.-
#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;
}
Desde ya muchas gracias
Saludos
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
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.
Citarel 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.
Mil disculpas, el bucle es while y el operador es el que tipea el teclado.-
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.
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.
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:
float n = 456.789;
int digitos = 0;
while( (float)(int)n != n){
digitos += 1;
n *= 10;
}
Si quieres lograr otra cosa, explícalo mejor.
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.
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.
Cita de: NOB2014 en 9 Enero 2016, 20:15 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.
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. -
while(x <= 6 ){
decimal *=10;
x++;
temp = decimal + 1e-9;
if( temp == decimal ) {break;}
printf("\n decimal = %g ==> temp = %d", decimal, temp);
}
(http://i64.tinypic.com/200fzb9.png)
Saludos.
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.
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.
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.-
#include<stdio.h>
int main( void ){
int numero = 1854, i, b = 1, temp = 0, x;
for( i = 0; i < 32; i++ ){
temp += numero & b;
x = numero & b;
if( x > 0 ) printf("\n bit encendido ==> [%d] = %d", i, x);
b *= 2;
}
printf( "\n\n La direccion de memoria %p contiene el valor %d\n\n", &numero, temp );
return 0;
}
gracias ivancea96 por la aclaración.-
A seguir intentando.
Saludos
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.
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.-
#include <stdio.h>
#include <float.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;
}
(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.
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.
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
while( contador < 20 && fabs(numero - round(numero)) != 0 ) {
contador++;
numero *= 10;
printf("Numero es ...: %lf, van: %d decimales\n", numero, contador );
printf(" Diferencia: %.2E\n", fabs(numero - round(numero)));
}
(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:
while( contador < 20 && fabs(numero - round(numero)) > FLT_EPSILON ) {
contador++;
numero *= 10;
printf("Numero es ...: %lf, van: %d decimales\n", numero, contador );
printf(" Diferencia: %.2E\n", fabs(numero - round(numero)));
}
}
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"
Cita de: Yoel Alejandro en 18 Enero 2016, 18:42 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/
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.
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.
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
Hola, Yoel.
Maravilloso, posibilita un máximo de 14 dígitos, más que suficiente. -
Saludos.
Daniel
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 #include <stdlib.h>
#include <stdio.h>
int main()
{
div_t d;
int num, denom;
double aux;
printf( "Escriba el numerador y el denominador (separados por un espacio):\n" );
scanf( "%d %d", &num, &denom );
d = div( num, denom );
aux=d.rem/(double)denom;
printf( "ldiv( %d, %d ) : cociente = %d, resto = %f\n", num, denom, d.quot, aux );
return 0;
}
(http://i.imgur.com/iPrzfkG.png)
Espero que me contestes
Esta solución permite 30 decimales !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) :silbar: :silbar: :silbar:
#include <stdlib.h>
#include <stdio.h>
int main()
{
div_t d;
int num, denom;
double aux;
printf( "Escriba el numerador y el denominador (separados por un espacio):\n" );
scanf( "%d %d", &num, &denom );
d = div( num, denom );
aux=d.rem/(double)denom;
printf( "ldiv( %d, %d ) : cociente = %d, resto = %.30lf\n", num, denom, d.quot, aux );
return 0;
}
(http://i.imgur.com/XlBEHeP.png)
De esos decimales, solo 15 son reales.
Cita de: ivancea96 en 30 Enero 2016, 23:54 PM
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.