|
|
View previous topic :: View next topic |
Author |
Message |
Robotan
Joined: 12 Jul 2008 Posts: 18 Location: Canada
|
Floating Point Division |
Posted: Sat Jul 12, 2008 10:56 pm |
|
|
Hello,
I have not used floats before, but I have an application where they would make my life much easier. Unfortunately, using them doesn't seem to be as straightforward as I would like. I was having trouble with the calculations in my code, and I isolated the problem to be with the division. Take a look at the comments below.
Code: |
#include <16F877A.h>
#device ADC=10
#device ICD=TRUE
#fuses HS,NOWDT,PUT,NOLVP,NOBROWNOUT
#use delay (clock=20000000)
#use i2c(master,sda=PIN_C4,scl=PIN_C3,FORCE_HW)
#include <LCD.C>
#include <math.h>
void initialize()
{
lcd_init();
delay_ms(1000);
}
void main()
{
float F,A;
initialize();
A = 1/151; //this gives 0
printf(lcd_putc,"\fA:%f",A);
delay_ms(1000);
A = 1;
A/=151; //this gives the correct value
printf(lcd_putc,"\fA:%f",A);
}
|
So it looks to me like you have to stick to a single math operation per line for floats. Is this normal? Is this something to do with the compiler? I should mention I am using version 3.212. Are there any other peculiarities with floats that I should keep in mind?
Rob |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Jul 12, 2008 11:51 pm |
|
|
No, it's that the compiler thinks you want to do integer math.
In the 2nd case, it knows that you want floating point math, because
one of the operands is declared as floating point.
Also, with CCS you need to give it a width and a precision.
It's much more reliable that way. Notice in the program below
that I give it %7.5f in the format string.
The program below displays the following output:
Code: | #include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
//====================================
void main()
{
float A;
A = 1/151.0;
printf("%7.5f \n\r", A);
while(1);
} |
|
|
|
Ttelmah Guest
|
|
Posted: Sun Jul 13, 2008 2:21 am |
|
|
As a further comment, the response for the first line, would be the same with any standard C.
The rules are a little obscure, and CCS, is _slightly_ stricter, than most C's, but basically, the compiler looks at the 'types' of the components involved in a sum, and then uses the arithmetic of the 'highest' type. The result, is not considered part of the 'sum'.
PCM shows what is needed, but I'll just try to give some examples to make it clearer.
So:
1/151 - both parts are integers, hence use integer arithmetic.
1/151.0 - note the decimal point. Now the second part is a 'float', hence use float arithmetic.
float a;
a=1; - Here '1' (integer), is automatically converted to a float.
a/151 - here 'a' is a float, so use float arithmetic.
Now comes the bit where CCS, may give problems.
4.0*(1/151) - on most C compilers, this would guarantee the use of float. However CCS, _may_ (not sure if it would in this exact case), evaluate the bracketed part _first_. Since both entries inside the brackets are integer, if this happens, you would get this done using integer arithmetic, and then the result of this, multiplied by 4.0, using float. Basically, CCS, at times does not 'propagate back' the higher type used latter.
At any time, you can force type conversion, using a 'cast', so:
1/(float)151 - will now use float arithmetic, since the integer '151`, is converted to a float, before use.
In your first example, all C's should do the same.
The big advantage of the CCS approach, is that it results in smaller code, only using the slower, and much bulkier 'types, when needed, but it puts the onus on _you_ to ensure that when entering any line, a suitable arithmetic type will be used. As an example of the saving:
int fred;
float res;
fred =5;
res=4.2/(289*fred)
CCS, will evaluate the bracketed multiplication, using int16 arithmetic. The difference, on a 4Mhz processor, is between 236uSec to evaluate this in int16, and 890uSec to do the same with float. This may be a very important saving.
Best Wshes |
|
|
Robotan
Joined: 12 Jul 2008 Posts: 18 Location: Canada
|
|
Posted: Sun Jul 13, 2008 9:40 am |
|
|
Thanks for the quick and helpful replies. I had forgotten how C treats floating point arithmetic. I can understand now why the compiler puts the onus on the programmer to explicitly state whether the calculation should be done with ints or floats. For me the easiest solution is to put a decimal in every constant I use.
Rob |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|