Exponentes en CCS

es la primer vez se me presenta la necesidad de usar exponentes en CCS

tengo este codigo:
Código:
#include <16F877A.h> 
//#fuses XT,NOWDT,NOPROTECT,NOLVP 
#use delay(clock= 4000000) 

#include "lcd.c"
#include "kbd_LIB.c"
#include <string.h>
#INCLUDE <stdlib.h>
[COLOR="red"]#INCLUDE <math.h>[/COLOR]


void main()
{
   char nume[10];
   char dece [10];
   char actual=0;
   short ed=true;
   
   int i=0,d=0;
[COLOR="Red"]   float num1;[/COLOR]
   float num2;
   float valor; 
  
   lcd_init();
   kbd_init();   
   port_b_pullups(TRUE); 
   set_tris_c(0xff);

   while(true)
   {  actual=getch();
      switch(actual)
      {  case '+':
[COLOR="Red"]             num1= pow(10,2);
            printf(lcd_putc,"%u",num1);[/COLOR]
         break;
        default:
         lcd_putc(actual);
         if (ed) {nume[i]=actual;i++; } else {dece[d]=actual;d++;}  
        break;
     }
    }
   }

en el resultado me pone 84 alguien me puede echar una mano, deberia ser 10^2=100 :eek:

resalto en rojo lo escencial del codigo
 
Última edición:
Hola amigo, creo que el error esta en: %u, la u se usa para enteros sin signo, para flotantes se usa la f.


printf(lcd_putc,"%u",num1);
 
yo creo que es el pow(x,y)

pongo:
num1=pow(10,2);
printf(lcd_putc,"%5.2g",num1);

y me pone 0.00

pero si pongo:
num1=10.3456;
printf(lcd_putc,"%5.2g",num1);

me pone 10.35 lo que es correcto redondea a 2 digitos.
 
No, el operador "^" es para hacer un OR o algo así, no para potenciar.

Siendo un número conocido y una potencia conocida a lo mejor sale mejor hacer un bucle; si es un entero elevado a un entero sale entero y no float y eso requere mucha menos máquina
Algo así:
int potencia(a,b){
potencia = a;
for(int x, x<b,x++){
potencia= a * potencia;
}
return potencia;
}

Seguro que tiene errores pero algo así pudría ser mas rápido que una potencia genérica de float elevado a float.
 
Última edición:
Me parece que si es un error del ccs ya revice la librería de math para hacerlo directamente con exp y log y sigue haciendo las cosas mal voy a intententar hacerlo a "piedra y cincel" con el ciclo for como me sugieres scooter
 
A mi me funciona bien, el resultado de pow(10,2) me dá "99.99"

Usé este simple código para probar...
Código:
#include <16f877a.h>
#use     delay(crystal = 4MHz)
#include <lcd.c>
#include <math.h>

void main(){
   float num_x=10,num_y=2,res;
   lcd_init();
      
      res = pow(num_x,num_y);
      printf(lcd_putc,"\fValor: %f",res);
}

Saludos.
 
No, el operador "^" es para hacer un OR o algo así, no para potenciar.

Siendo un número conocido y una potencia conocida a lo mejor sale mejor hacer un bucle; si es un entero elevado a un entero sale entero y no float y eso requere mucha menos máquina
Algo así:
int potencia(a,b){
potencia = a;
for(int x, x<b,x++){
potencia= a * potencia;
}
return potencia;
}

Seguro que tiene errores pero algo así pudría ser mas rápido que una potencia genérica de float elevado a float.

Es verdad Scooter el comentario que haces sobre el operador "^", se utiliza para hacer mascara XOR.
 
Última edición:
Por gusto habría que medir el tiempo de pow y del bucle a ver. Creo que el bucle es mas rápido.

El pow es MUCHO mas costoso computacionalmente.

Cuando el exponente es entero es una burrada usarlo, para eso se escribe directamente x*x, x*x*x etc (o se usa un #define, o un rutina) . Ni hablar si los dos son enteros.
Tiene que usarse solamente con exponentes reales o racionales (pow(x,1.25), pow(x,0.3333333) que es cuando realmente se la necesita, no para evaluar un polinomio.


Muchas veces veo que usan con total tranquilidad tipos float con variables que son siempre enteras. Lo mismo que antes, las operaciones en punto flotante son MUCHO mas costosas computacionalmente que en enteros.
Solamente tiene sentido cuando debido al rango de las variables y al tipo de operaciones a realizar pueda haber overflow/underflow.
Aunque tampoco es solución mágica usar float, porque si no se tiene cuidado, debido a los errores de redondeo/truncamiento le va a dar cualquier cosa.
Cuando pasa esto último ni se dan cuenta, le echan la culpa al compilador, al micro o al autor del algoritmo ;)
 
a darkbytes:

ya probe tu codigo y no me funciono, estoy pensando que mi libreria math tiene algun error, quizas causado por mi accidentalmente o asi estaba, podrias pasarme la tuya para verificar que sea eso.

a eduardo:

analice el codigo del pow y efectivamente es un desperdicio de recursos, al ultimo voy a hacer lo que dices del x*x*x*x etc porque si son enteros ambos, en realidad lo que quiero es de un entero pasarlo a decimales

es decir si tengo 12345 (entero) pasarlo a decimal .12345 la formula qu pensaba utilizar es:

12345 / (10^5) =.12345 el 12345 esta almacenado en un arreglo es decir:
valor[0]=1
valor[1]=2
valor[2]=3
valor[3]=4
valor[4]=5
del arreglo lo paso con el atoi a una variable que es la que quiero pasar a decimales, espero haberme explicado:D comento esto para darles un panorama mas amplio de lo que pretendo. quizas hay un algoritmo mas eficiente que desconozco.
 
ya probé tu código y no me funcionó, estoy pensando que mi librería math tiene algun error, quizás causado por mi accidentalmente o así estaba, ¿podrías pasarme la tuya para verificar que sea eso?
Espero que sea eso, a mi si me muestra bien los resultados, si no, tendrás que reinstalar o actualizar el programa.

Suerte.
 

Adjuntos

  • MATH.zip
    7.5 KB · Visitas: 33
...
analice el codigo del pow y efectivamente es un desperdicio de recursos, al ultimo voy a hacer lo que dices del x*x*x*x etc porque si son enteros ambos, en realidad lo que quiero es de un entero pasarlo a decimales

es decir si tengo 12345 (entero) pasarlo a decimal .12345 la formula qu pensaba utilizar es:

12345 / (10^5) =.12345 el 12345 esta almacenado en un arreglo es decir:
valor[0]=1
valor[1]=2
valor[2]=3
valor[3]=4
valor[4]=5
del arreglo lo paso con el atoi a una variable que es la que quiero pasar a decimales, espero haberme explicado:D comento esto para darles un panorama mas amplio de lo que pretendo. quizas hay un algoritmo mas eficiente que desconozco.

:confused: Pero 10^5 es una constante, no hay que calcular nada. Simplemente escribir 12345/100000.

También se puede implementar sin atoi con cadenas de longitud variable.
Si k fuera el índice del último dígito hacés:

Código:
    int i = k ;
    valorfloat = valor[i] - 0x30 ;
    valorfloat /= 10. ;
    do {        
        valorfloat += valor[--i] - 0x30 ;
        valorfloat /= 10. ;
    } while(i>0) ;

De todas formas, sigo sin tener claro para que convertís la cadena a float .12345
 
Pero 10^5 es una constante, no hay que calcular nada. Simplemente escribir 12345/100000.

no, puse el 10^5 porque 12345 son 5 digitos si tuviera 123 seria 10^3 etc el exponente lo manejare con un contador variable

De todas formas, sigo sin tener claro para que convertís la cadena a float .12345

estoy intentando hacer una calculadora con decimales, yo digito una tecla y esa tecla va a un arreglo para enteros por ejemplo enteros[10] al presionar el punto decimal se empiezan a ir a otro arreglo por ejemplo decimales[10] en cada caso hay una variable como contador que se va incrementado cada que se agrega un digito, la idea es sumar en una variable float ambos arreglos o sea enteros+ decimales.

voy a intentar implementar el codigo que me facilitaste.



a darkytes:

reemplace la libreria y ya funciono muchas gracias, pero efectivamente si pongo pow(10,2) me pone 99.99, me quedo con la inquietud si yo dañe la libreria o la version que tengo esta mal, que por cierto tuve que reemplazar todos los float32 por float mi version de ccs no tiene el float32.
 
Última edición:
Los float acumulan error siempre. Los de un pc igual son de 8 o mas bytes y no es perceptible, si los del pic son de 6 bytes o menos se nota mas, a cambio es mas rápido.
 
...estoy intentando hacer una calculadora con decimales, yo digito una tecla y esa tecla va a un arreglo para enteros por ejemplo enteros[10] al presionar el punto decimal se empiezan a ir a otro arreglo por ejemplo decimales[10] en cada caso hay una variable como contador que se va incrementado cada que se agrega un digito, la idea es sumar en una variable float ambos arreglos o sea enteros+ decimales.

Si se trata de una calculadora "demo", para eso usá directamente atof().
Pero si lo que buscás es que realmente trabaje como una calculadora, con float (32bits) te quedás re-corta.

El tipo float no te sirve para operaciones genéricas porque al ser grande el error por truncamiento, si las operaciones no se hacen de una forma que minimice el error te da cualquier cosa.

Para algo genérico tiene que ser por lo menos doble precisión (64bit), el problema que vas muerta con el CCS y no conozco librerías que contemplen un "float64" (tendrías que escribir tus propias rutinas de punto flotante)
 
Atrás
Arriba