Problem with float division(float A, float B)

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Since the avr Gcc is not able to perform a division without truncating the float, I performed a prototype that worked well so far in Avr studio 4

I'm trying to use it within a project in Avr studio 5 and I get the following error message "control reaches end of non-void function"

 

here is the code:

 

#ifndef division
#define division

#include <stdlib.h>
#include <math.h>
#include <avr/io.h>

float divis(float x,float y);

float divis(float x,float y)
{ 
 if((x>0) && (y>0))
 return (exp(log(x)-log(y)));
 
 if((x<0) && (y>0))
 return (-exp(log(-x)-log(y)));

 if((x>0) && (y<0))
 return (-exp(log(x)-log(-y)));

 if((y==0) && (x!=0))
 return 9999;
 
 if((x==0) && (y!=0))
 return 0;
}

#endif

Any idea about what's happening ????

This topic has a solution.
Last Edited: Wed. Nov 12, 2014 - 10:05 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What do you want to do?

 

Of course you can do f-p division.

 

Apart from returning rather 'strange' values for division by zero,    you will introduce small errors by calling log() and exp().

Your solution looks a bit like people using pow() when they want to shift bits in an integer.

 

I am intrigued by where you got the "avr Gcc is not able to perform a division without truncating the float"

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For example when I try to display:

 

- 100/5 it gives 20 which is OK

- 10/30 it gives 0 (so it truncates the value after the comma)

 

What is the ideal way of making divisions and getting full values whitout being truncated???

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you want a f-p result:   100.0/5.0 gives 20.0

10.0/30.0 gives 0.3333333

 

If you want the integer value of 0.333333 it will be 0

 

An integer is always truncated.    You can't have a fractional integer !

 

Most maths in embedded apps is done with integers.

However,   f-p can be very handy for scaling integers without having to worry about underflow/overflow.  e.g.

 

int centigrade;

...

int farenheit = 1.8 * centigrade + 32;

You can do the calculation in integers but you need to be careful.   e.g.

int centigrade;

...

int farenheit = (180 * centigrade) / 100  + 32;

This will work fine for "room temperatures"   but will go seriously wrong for "high temperatures"

If you multiply by 9 and divide by 5,   you will be ok for terrestrial temperatures.

 

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You need to link in the floating point print by either checking a box in the project options in the ide, or erasing a comment in the makefile. Its a checkbox on the imagecraft ide. Dont forget to use the %7.1f spec to print out the numbers.

 

Imagecraft compiler user

Last Edited: Tue. Nov 11, 2014 - 11:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Avr studion 5
Very buggy, apparently.  Upgrade to the latest 6.2.whatever, or roll back to 4.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you all....David, I did not know that ...(Thanks)....

Now that everything seems good I'm facing another problem:

How to add the math.h? (I'm getting an error concerning the linking)

is there any good tutorial explaining how to add libraries step by step ???

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

#include <math.h>

 

Make sure that you have selected libm.a when linking.     (it is the default with AS6.2)

 

Regarding the C language,  modular programming,  ...

There are many textbooks and online tutorials.     It is a lot easier to do exercises on the PC with a regular PC compiler (and IDE).

 

Leave the AVR until you have got the hang of the basics.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How to add the math.h? (I'm getting an error concerning the linking)

is there any good tutorial explaining how to add libraries step by step ???

You don't actually have to do anything. By default AS6 creates projects that include -lm in the linking phase (which links to libm.a - the float math library). In fact if all you are doing is arithmetic you don't even need:

#include <math.h>

that's only required when you want to call specific float math functions like sin() or pow() or whatever. So something as simple as:

#inlcude <avr/io.h>

int a, b, c;

int main(void) {
    a = 10.0;
    b = 30.0;
    c = a / b;
    DDRB = 0xFF;
    PORTB = c * 10;
}

should produce the bit pattern 00000011 on PORTB. No need for libs or floating specific includes.

 

BTW it is often cleaner to have only one "return" point from a function so your original routine might be:

float divis(float x,float y)
{
 float retval = 0.0; // set to 0.0 just in case none of the following are met.
 
 if((x>0) && (y>0)) {
   retval = (exp(log(x)-log(y)));
 }
 
 if((x<0) && (y>0)) {
   retval = (-exp(log(-x)-log(y)));
 }

 if((x>0) && (y<0)) {
   retval = (-exp(log(x)-log(-y)));
 }

 if((y==0) && (x!=0)) {
   retval = 9999;
 }
 
 if((x==0) && (y!=0)) {
  retval = 0;
 }
 return retval;
}

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

#include <math.h>

that's only required when you want to call specific float math functions like sin() or pow() or whatever. So something as simple as:

#inlcude <avr/io.h>

int a, b, c;

int main(void) {
    a = 10.0;
    b = 30.0;
    c = a / b;
    DDRB = 0xFF;
    PORTB = c * 10;
}

should produce the bit pattern 00000011 on PORTB. No need for libs or floating specific includes.

 

No, it won't.    You are just assigning to integers.    The expressions will be evaluated as integers.  

 

This will probably do what you expect:

#include <avr/io.h>

float a, b, c;

int main(void) {
    a = 10.0;
    b = 30.0;
    c = a / b;
    DDRB = 0xFF;
    PORTB = c * 10;
}

 

You can force an expression to be evaluated in f-p by using casts or f-p constants.   e.g.

int c, d, e;
...
c = 3.333 * d;      //use a f-p constant
...
c = (float)d / e;   //use a f-p cast

Both of those assignments will be evaluated in f-p.    However the result will be truncated when it becomes assigned to an integer.

 

The rules for type promotion and evaluating expressions are fairly difficult to grasp.

It is probably safer to just use float variables.

 

David.

Last Edited: Wed. Nov 12, 2014 - 11:17 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just installed Atmel studio 6.2 and as clawson said,  AS6 creates projects that include -lm in the linking phase (which links to libm.a - the float math Library).

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simple ops like add, subtract, multiply, divide are handled automatically.

 

You only need <math.h> for the 'advanced' functions like sqrt(), log(), sin(), ...

 

As a general rule,   you don't actually need libm.a for the +, -, *, /

However,   avr-gcc's libm.a has better implementations of +, -, etc.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are just assigning to integers.  

Ah so you spotted the deliberate error then? Just making sure everyone was on their toes. a,b,c were supposed to have been "float" not "int". Oops! blush