# Exponentes en CCS



## LaElectronicaMeOdia (Oct 13, 2013)

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

tengo este codigo:

```
#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 

resalto en rojo lo escencial del codigo


----------



## jcristhian_1 (Oct 13, 2013)

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


----------



## Scooter (Oct 13, 2013)

jcristhian_1 dijo:


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



Si, en c ando cojo pero yo también creo que es eso.


----------



## LaElectronicaMeOdia (Oct 13, 2013)

algo anda raro.

puse:

             num1= pow(10,2);
            printf(lcd_putc,"%f",num1);

y me pone 0.00

despues puse:

             num1= pow(10,2);
            printf(lcd_putc,"%10.5w",num1);

y me pone 35774.33940


----------



## Eduardo (Oct 13, 2013)

LaElectronicaMeOdia dijo:


> algo anda raro.
> 
> puse:
> 
> ...



 Probá especificando a cantidad de dígitos: 

printf(lcd_putc,"%5.2f",num1);   // trunca
o  
printf(lcd_putc,"%5.2g",num1);  // redondea


----------



## LaElectronicaMeOdia (Oct 13, 2013)

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.


----------



## Eduardo (Oct 13, 2013)

LaElectronicaMeOdia dijo:


> yo creo que es el pow(x,y)



Si, capaz que al compilar no cambia el 'y' entero a float.

¿Y con pow( 10. , 2. )?


----------



## Gudino Roberto duberlin (Oct 13, 2013)

Hola Amigo, bueno estoy similar que Scooter en C, pero en lugar de utilizar   num1= pow(10,2);   prueba con num1=10^2;


----------



## Scooter (Oct 13, 2013)

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.


----------



## LaElectronicaMeOdia (Oct 13, 2013)

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


----------



## D@rkbytes (Oct 13, 2013)

A mi me funciona bien, el resultado de pow(10,2) me dá "99.99"

Usé este simple código para probar...

```
#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.


----------



## Gudino Roberto duberlin (Oct 13, 2013)

Scooter dijo:


> 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í:
> ...



Es verdad Scooter el comentario que haces sobre el operador "^", se utiliza para hacer mascara XOR.


----------



## Scooter (Oct 14, 2013)

Por gusto habría que medir el tiempo de pow y del bucle a ver. Creo que el bucle es mas rápido.


----------



## Eduardo (Oct 14, 2013)

Scooter dijo:


> 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


----------



## LaElectronicaMeOdia (Oct 14, 2013)

*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 comento esto para darles un panorama mas amplio de lo que pretendo. quizas hay un algoritmo mas eficiente que desconozco.


----------



## D@rkbytes (Oct 14, 2013)

LaElectronicaMeOdia dijo:


> 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.


----------



## Eduardo (Oct 14, 2013)

LaElectronicaMeOdia dijo:


> ...
> 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:
> ...



 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:


```
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


----------



## LaElectronicaMeOdia (Oct 15, 2013)

> 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.


----------



## Scooter (Oct 15, 2013)

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.


----------



## Eduardo (Oct 15, 2013)

LaElectronicaMeOdia dijo:


> ...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)


----------



## ingeniero18 (Oct 23, 2015)

D@rkbytes dijo:


> Espero que sea eso, a mi si me muestra bien los resultados, si no, tendrás que reinstalar o actualizar el programa.
> 
> Suerte.



Estoy teniendo un problema muy parecido con la librería math.h, ya que la función log10 no sólo no funciona sino que no devuelve valor alguno. Al simular en proteus me aparece la variable que tendría que tener el resultado como "unspecified". 
Reemplacé mi librería por la tuya y tampoco.
Declaré la variable como float y float32 y tampoco.

Qué piensan????


----------



## D@rkbytes (Oct 23, 2015)

ingeniero18 dijo:


> Reemplacé mi librería por la tuya y tampoco.
> Declaré la variable como float y float32 y tampoco.
> 
> *¿Qué piensan?*


Que algo estás haciendo mal porque si funciona la instrucción* log10(x)*;

Adjunto el programa de ejemplo, pero primero ejecuta la simulación así con los archivos adjuntos.
No lo compiles para que puedas ver el funcionamiento.
Después realiza una compilación y ve si sigue funcionando.
Si no te funciona, entonces deberás reinstalar o actualizar el compilador.


Nota:
Usé PIC C Compiler v5.048 pero la librería math.h ha funcionado bien desde versiones anteriores.

Suerte.


----------



## ingeniero18 (Oct 23, 2015)

Solucionado!!! Después de buscar la solución durante dos días, llegué a la conclusión de que es la versión del proteus.

Para que proteus te reconozca variables tipo float y muestre su valor, hay que agregar {DT_FLOAT=MICROCHIP_BIGENDIAN} en el campo "Other Properties" dentro de las propiedades del micro. El tema es que esto sólo funciona para versiones de proteus desde el 2011 en adelante, por lo que me instalé la 7.10 y anduvo al toque.

Gracias!!!


----------

