[Solucionado] Establecer la cantidad de dígitos a la derecha de la coma [C]

Iniciado por NOB2014, 9 Enero 2016, 15:34 PM

0 Miembros y 3 Visitantes están viendo este tema.

ivancea96

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.

NOB2014

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);
}




Saludos.
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

ivancea96

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.

MAFUS

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.

NOB2014

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
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

MAFUS

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.

NOB2014

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;
}






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

Saludos.
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

MAFUS

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.

Yoel Alejandro

#18
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 (cpp) [Seleccionar]

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"
Saludos, Yoel.
P.D..-   Para mayores dudas, puedes enviarme un mensaje personal (M.P.)

Eternal Idol

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/
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón