CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Floating Point Division

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Robotan



Joined: 12 Jul 2008
Posts: 18
Location: Canada

View user's profile Send private message

Floating Point Division
PostPosted: Sat Jul 12, 2008 10:56 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Jul 12, 2008 11:51 pm     Reply with quote

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:
Quote:
0.00662

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







PostPosted: Sun Jul 13, 2008 2:21 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Jul 13, 2008 9:40 am     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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