Chicos, ya se que los foat en c, tienen muchos muchos errores de precisión, que son caca mala y que no hay que usarlos. Pero quiero usar decimales, de un número indeterminado de cifras decimales, y me gustaría poder descomponer en dos enteros la parte entera, y la parte decimal. Ejemplo
12.18
entero a=12;
entero b=18;
He usado varios métodos, pero todos me dan problemas con la precisión. Si a alguno se le ocurre como solucionarlo, yo, le doy mi mano en matrimonio,
Pequeño ejemplo que funciona a veces;
[code language="bennu"]#include<stdio.h>
#include<conio2.h>
int main(){
char a;
int i,j,num,inc;
double dec;
while(a!='c'){
num=0;
inc=10;
printf("\n\t Introduzca un número decimal, pazguato:");
scanf("%lf",&dec);
if(dec>1.0){
i=(int)dec;
dec=(float)dec-i;
}
printf("\n Numero sin parte entera: %lf\n",dec);
do{
i=dec*inc;
j=dec*inc*10;
inc*=10;
printf("\n i:%d j:%d",i,j);
}while(j-(i*10)!=0);
num=i;
printf("\n Numero convertido a entero: %d",num);
a=getch();
}//while
}//main
[/code]
Un saludo.
Pues si, deberías de trabajar con los dos int desde el principio haciendo algo como un scanf("%ld.%ld")
De todos modos el codigo siguiente me va bien para todos los casos que he probado.
#include "stdio.h"
#include "math.h"
#include "string.h"
int main()
{
double real;
int parteEntera;
int parteDecimal;
char buffer[255];
printf("Número real:");
scanf("%lf",&real);
fflush(stdin);
parteEntera=real;
printf("Parte Entera:%d\n",parteEntera);
real-=parteEntera;
printf("Restante:%lf (double)\n",real);
sprintf(buffer,"%lf",real);
printf("Restante:%s (string)\n",buffer);
int i=strlen(buffer)-1;
while(buffer[i]=='0'){
buffer[i]=0;
i--;
}
printf("Restante:%s (string reducido)\n",buffer);
real*=pow(10,strlen(buffer)-2);
printf("Parte Decimal:%lf (double)\n",real);
parteDecimal=round(real);
printf("Parte Decimal:%d (int)\n",parteDecimal);
return 0;
}
si quieren evitar usar flotantes por la precision, entonces no hay que usar flotantes en ninguna etapa.
Tengo que usar un float, porque en el ejemplo lo capturo por teclado, pero en el programa lo recibo como resultado de una división de enteros, de la cual me tengo que quedar con la parte decimal y convertira a entera, y no se, a priori, cuantos decimales me va a dar la división.
Muchas gracias.
trabaja con numeros multiplicados por 1000 o 100, segun la cantidad de decimales que necesites... y trabaja con enteros...
por ejemplo
1.23 = 123
245.3 = 24530
trabaja directamente con numeros multiplicados, no uses decimales, y ahi ya sabes que los ultimos 2 (o N) digitos del numero son los decimales...
Splinter, eso da algunos problemas al multiplicar y dividir que no has mencionado. 1.23 = 123/100(es decir, 123 corriendo 2 lugares la coma); y 1.23+2.02 = 123/100+202/100 = (123+202)/100(corriendo 2 lugares la coma otra vez). Sin embargo, si multiplicas, 1.23*2.02 = 123/100*202/100 = (123*202)/10000; es decir, que si multiplicas 1.23 por 2.02 utilizando tu sistema(123*202), el resultado tendrás que correrle la coma 4 posiciones y no 2 para que te de el auténtico resultado de 1.23*2.02.
Sin embargo, al dividirlo, te da lo mismo 123/202 que 1.23/2.02; no hay que correr la coma porque ambos resultados te dan lo mismo, y en el caso de que lo hagas con enteros da 0; así que creo que no es muy buena solución la que propones.
Caramba!
Yo no dije que multiplique ni divida nada...
dije que tomando una base, segun la cantidad de decimales que necesite, trabaje siempre con numeros "ya multiplicados" (sin hacer ninguna multiplicacion ni division para obtenerlos)...
si necesita 2 decimales, el sabra que los 2 ultimos digitos del numero son decimales
si necesita 3 decimales, el sabra que los 3 ultimos digitos del numero son decimales
el sistema funciona perfectamente, tanto funciona que es lo que se usa desde hace muchos años en todo sistema de transacciones financieras a nivel mundial (ATM, compras con tarjetas de credito, debito, y un largo etc...) ... (para mas detalle ISO8583, campo 4 -ammount-)
EDIT: Yo hablaba de la representacion... es cierto, no lo mencione, si multiplicas 2 numeros tendras que correr 4 la coma y descartar los 2 ultimos digitos.
para el caso de las divisiones, hay que multiplicar uno de los miembros por 100 o por la base que se decida usa...
por ejemplo,
si tenemos 123/456
debemos hacer
123*100/456 = 26 = 026 = 0.26
ya que estamos vamos a poner que hacer para la multiplicacion:
( 123 * 456 ) / 100 = 560 = 5.60
estas formulas dan los valores adecuados siguiendo la misma norma.
resumen:
suma: a + b
resta: a - b
multiplicacion: (a*b)/100
division: (a*100)/b
siempre usar enteros... obviamente nos encontraremos con el limite de los enteros, pero no tendremos problemas de redondeo.
Eso está muy bien cuando sabes de antemano cuantos decimales vas a usar.
Pero, si no lo sabes?
Es decir, tenemos a/b, que va a dar decimales, pero da la casualidad de que a es un numero dado por teclado y b un numero aleatorio. Entonces ¿como predecir cuantos decimales va a dar?
a=134
b=99
da 1,3673469387755102040816326530612
¿como adivino cuantos decimales va a dar?
¿pongo un límite de decimales y punto?
digo, máximo 10 decimales. Vale ¿y como adivino si son menos?
a=133
b=50
da 2.66, vaya, ahora son solo 2 decimales.
¿que criterio puedo poner para predecir el numero de decimales aún con un tope?
Gracias, colegas.
no importa cuantos decimales vengan, lo que importa son los que vos vas a usar en tu sistema...
claro, vos definis y pones su limite.
tantos decimales, olvidate.
por que no explicas bien que queres hacer, para que lo necesitas?
mira esto...
http://msdn.microsoft.com/en-us/library/c151dt3s.aspx
http://www.physics.ohio-state.edu/~dws/grouplinks/floating_point_math.pdf
http://docs.sun.com/source/806-3568/ncg_goldberg.html
informacion realmente cool!
Quote from: Danielo515 on March 27, 2009, 10:46:44 PM
Eso está muy bien cuando sabes de antemano cuantos decimales vas a usar.
Pero, si no lo sabes?
Es decir, tenemos a/b, que va a dar decimales, pero da la casualidad de que a es un numero dado por teclado y b un numero aleatorio. Entonces ¿como predecir cuantos decimales va a dar?
a=134
b=99
da 1,3673469387755102040816326530612
¿como adivino cuantos decimales va a dar?
¿pongo un límite de decimales y punto?
digo, máximo 10 decimales. Vale ¿y como adivino si son menos?
a=133
b=50
da 2.66, vaya, ahora son solo 2 decimales.
¿que criterio puedo poner para predecir el numero de decimales aún con un tope?
Gracias, colegas.
Tú sólo decides cuántos decimales quieres usar tú, si te dan menos, se trunca, si te dan más, te salen ceros. Luego en esos dos casos que has puesto, suponiendo que hubieras decidido hacerlo con 5 decimales te quedaría: 1,36734 en el primer caso(136734) y 2,66000 en el segundo(266000)
Al final he tenido que tomar la decisión de tomar un numero determinado de decimales.
Era para un sistema de generación de números aleatorios (bastante malo por cierto) que se quedaba con la parte decimal de ciertas operaciones, y la parte decimal de ese numero era uno de los números aleatorios y la semilla del siguiente.
si daba 1,52 pues el 52 sería un numero aleatorio y la semilla para el siguiente.
Al final decidí tomar tantos decimales como cifras tuviera la semilla inicial.
Un saludo y muchas gracias.
para numeros aleatoreos podrias usar get_timer y tomar algunos digitos... o alguna combinacion de operaciones sobre get_timer... si bien es un contador, en los momentos en que lo vas a requerir creo que te dar unos resultados bastante random.
Si el programa no se ejecuta siempre igual, es decir, necesita los numeros random en un momento indeterminado de tiempo, con los timers basta, si no, pues se le añade alguna operación con la hora y fechas actuales y listo, más random imposible.