Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Dividing numbers in PIC C

Status
Not open for further replies.

namtey

New Member
Hi

I have (I think) a simple problem. I am using the C18 compiler to write code to be used on a pic 18f4620 but at the moment am only compiling the code and running it with MPSIM.

I need to divide 2 numbers , which will result in a floating point number. However when I try this with the following code and watch variable j it returns a value of 2.0, not 2.5.

double j;
unsigned char i, Byte0, Byte1, Byte2, Byte3, x, y, z;
unsigned long FTW, bit32, Fo, Fref;

void main (void)
{
y=5;
z=2;
j=y/z;
}

I obviously do not understand the way floats are used in Microchip C.

Could somebody give me some advise please?
Thanks
 
You have to make one of the vars a float, try, j=(double)y/(double)z;

Mike.
 
im unfamiliar to the complier and pic's but im guessing you would to change "j" to a float variable

{
float a , b, j;
a = 5;
b = 2;

j = a/b;
}

I havnt coded for a long time, but im sure a double is classed as a int not a floating number.

if not could you not just shift ( << . >> ) your number to remove the decimal point and translate later (depends what your doing)
 
Last edited:
Thanks for the help.

You were right, I had to make all the variables in the calculation of type float for it to work.

Not sure why this is the case though, but hey!
 
The compiler uses the simplest maths it can unless you force it to use floats.

Mike.
 
In order to make your code more readable, you should make it obvious that you are dividing floats and not integers. In additional to changing the variable to floats, I suggest that you append a .0 to the end of the numbers to make it 100% obvious what you are doing. Yes, someone can look at variable declarations, or context, and figure it out, but spending a few seconds now may save minutes later.

Code:
double j, y, z;
unsigned char i, Byte0, Byte1, Byte2, Byte3, x;
unsigned long FTW, bit32, Fo, Fref;

void main (void)
{
   y=5.0;
   z=2.0;
   j=y/z;
}
 
In order to make your code more readable, you should make it obvious that you are dividing floats and not integers. In additional to changing the variable to floats, I suggest that you append a .0 to the end of the numbers to make it 100% obvious what you are doing. Yes, someone can look at variable declarations, or context, and figure it out, but spending a few seconds now may save minutes later.

Code:
double j, y, z;
unsigned char i, Byte0, Byte1, Byte2, Byte3, x;
unsigned long FTW, bit32, Fo, Fref;

void main (void)
{
   y=5.0;
   z=2.0;
   j=y/z;
}

That is a Microsoft solution, bloated and unnecessary. Casting to floats makes it perfectly obvious what is being done.

Mike.
 
Respectfully, I disagree.
 
Code:
double j;
unsigned char  x, y, z;
 
void main (void)
{
    y=5;
    z=2;
    j=y/z;
}
There is no mystery here.

The compiler generates code that evaluates the RHS and then assigns it to the LHS.
The RHS is y/z and both are int so it evaluates to 2.
To assign int 2 to the LHS there is an implicit conversion to double and 2 becomes 2.0.

In general I do not like to use floats or doubles. Most of the time you can scale the numbers to avoid their use.

3v0
 
Last edited:
Agree with not using floating point math as a general practice. Fixed point decimal is a commonplace replacement, lots of DSP's use it (5.23 and similar).
 
Last edited:
In order to make your code more readable, you should make it obvious that you are dividing floats and not integers. In additional to changing the variable to floats, I suggest that you append a .0 to the end of the numbers to make it 100% obvious what you are doing. Yes, someone can look at variable declarations, or context, and figure it out, but spending a few seconds now may save minutes later.

Code:
double j, y, z;
unsigned char i, Byte0, Byte1, Byte2, Byte3, x;
unsigned long FTW, bit32, Fo, Fref;

void main (void)
{
   y=5.0;
   z=2.0;
   j=y/z;
}

I understand where you are coming from with this...

But since everyone else says no heh... i suggest something similar...

Code:
double j, y, z;
unsigned char i, Byte0, Byte1, Byte2, Byte3, x;
unsigned long FTW, bit32, Fo, Fref;

void main (void)
{
   //y,z,j type = double
   y=5;
   z=2;
   j=y/z;
}
[/QUOTE]

This also doesnt alter any code so a small comment saves time so you dont have to jump to the top of code or another file to determine the type.
 
I'm with 3v0 on this one. Using floats is poor practice in microcontrollers unless absolutely necessary.

Why not just scale y with a binary factor and keep the result scaled?
y = (5*256);
z = 2;
j = (y/z);
(that only needs unsigned int for y)

y = (5 * 16); etc
works ok for y 0-15, and might allow you still to use unsigned char for all vars, a massive saving.
 
I'm actually more curious as to if Pommie was saying that adding trailing 0's is the MS bloated solution or if he meant that using floats/doubles is the bloated solution. I use integer math every time I can, but there are a few times I had to use floats.

If you are going to use floats, I still say that you should put a '.0' to the number, but I do agree that floats should be avoided when possible.

I'm with 3v0 on this one. Using floats is poor practice in microcontrollers unless absolutely necessary.

Why not just scale y with a binary factor and keep the result scaled?
y = (5*256);
z = 2;
j = (y/z);
(that only needs unsigned int for y)

y = (5 * 16); etc
works ok for y 0-15, and might allow you still to use unsigned char for all vars, a massive saving.

I don't really like using the *256 or *16, I prefer using *10 or *100 as it makes it much easier to debug. I understand the benefits of using the 256 or 16 as you can do it as shifts, however, if it is scaled by 10 it takes no math to debug. Just insert a break point and look at the variable. Don't need a calculator to figure out what the value is. However, I work in PIC24, PIN32, and ARM7 the vast majority of the time and the only thing I have to do is make sure that a function executes in 10mS or less and I'm golden.
 
Last edited:
I was saying that making all variables floats was a bloated way to achieve the desired outcome. In the example given, j needs to be a float, the others could be chars. Also, casting to double makes it extra obvious what is being done.

Mike.
 
hex to bcd conversion

hellooooooo
can anybody help to explain me the logic behind hex to bcd conversion..
m using pic16f887..
i m having the logic : adding 06 to hex number and if carry out of lower nibble does not occur then add FA ..then add 60 to hex no., if carry out of upper nibble does not occur then add A0 to it..

this logic is working with some of the hex numbers and not working for many other numbers like AA, BA...etc..

so can nybody help from this forum..m new to this forum...

thanx in advance






Hi

I have (I think) a simple problem. I am using the C18 compiler to write code to be used on a pic 18f4620 but at the moment am only compiling the code and running it with MPSIM.

I need to divide 2 numbers , which will result in a floating point number. However when I try this with the following code and watch variable j it returns a value of 2.0, not 2.5.

double j;
unsigned char i, Byte0, Byte1, Byte2, Byte3, x, y, z;
unsigned long FTW, bit32, Fo, Fref;

void main (void)
{
y=5;
z=2;
j=y/z;
}

I obviously do not understand the way floats are used in Microchip C.

Could somebody give me some advise please?
Thanks
 
Your logic will work correctly up to 99 as this is the biggest BCD number than can be contained in a byte.

Mike.
 
I was saying that making all variables floats was a bloated way to achieve the desired outcome. In the example given, j needs to be a float, the others could be chars. Also, casting to double makes it extra obvious what is being done.

Mike.

In that case, then respectfully, I agree.
 
I had to make all the variables in the calculation of type float for it to work.
-

You could have just done,
Code:
double j;
unsigned char i, Byte0, Byte1, Byte2, Byte3, x, y, z;
unsigned long FTW, bit32, Fo, Fref;

void main (void)
    { 
        y=5;
        z=2;
        j=(double)y/(double)z;
}

Mike.
 
Google for "Integer Promotion". This is an important term. Also search your compiler manual for this.

IP is a matter of C standards that all C compilers should either subscribe to, or list somewhere that they do something different. It comes down to several things:
1. It specifies where promotions to larger integers will occur. The left side of the equation never determines how the eq is interpreted during calculation. It's all the arguments on the right side. For equations which require multiple steps (add, mult, then divide), the type may even change multiple times.
2. Sometimes this automatic promotion will not be necessary, and consume excess resources to perform.
3. Some types of promotions, though potentially necessary for your application, are not done automatically. No one ever promotes an integer equation to a Float/Double.
4. Some types of promotion are unspecified by the standard and your compiler may or may not promote them.
5. You can often force the way integers are calculated by using a cast, but the compiler may overrule it in its actual implementation.

Also note that constants are evaluated and "folded" during the precompiler stage. As such, an integer may be assigned by a complicated calculation of float constants, either #defined as explicit constants or stated explicitly on the right hand side, and NO float code will be included in the program or executed. This is very handy at times for making clear code without making it any less efficient.

It is highly unlikely that you need a floating-point calc here. Everyone thinks they need FP early on, but rarely do. FP is quite slow to run, relatively speaking, and fixed-point type calculations can almost always do the job. In some cases they're more accurate, too.

You may find fixed-point math is easier and more efficient if you shift the value by considering it a mult/div of a power 2. You, as a programmer, will have to keep track of where the decimal is in the variable at any given time. Comment everywhere for documentation.
 
Last edited:
Pic 1937 timer problem

Hello..
I am using pic 1937 in my project. I am using timer0 as an interrupt. Now the problem i am facing is : when timer0 overflows, the corresponding flag bit gets set.. then it must go into its service routine..but it is not entering into its service routine..just it overflows and flag gets set.. and it restarts. not going into its routine.. can anybody suggest any solution or hint regarding this?

thank you so much in advance..
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top