Click here to Skip to main content
15,902,777 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello everyone,
I made the following function, which i use to drive stepper motor

Objective-C
int16 position2steps(double position)
{
   int16 steps = 0;
   if(!strcmp("HALF", step_mode))
      steps = (position / half_angle);
   else
      steps = (position / step_angle);
   return steps;
}

suppose this initial condition [ step_angle = 1.8 and half_angle = 0.9]
Now if (position = 0.9 and step_mode = half) this function should return 1

but if i use this function frequently it give 1 for some time but then it return 0 because the value = 0.99 and then converted to int = 0

i would like to know what is the problem and how to avoid it

Thanks in advance,
z3ngew
Posted
Comments
[no name] 5-Aug-13 6:31am    
http://floating-point-gui.de/

Quote:
but if i use this function frequently it give 1 for some time but then it return 0


This is a very strange comment because it should always return the same output for the same input.

Nevertheless not all numbers can be exactly represented as a double. This means you end up with something close. For this reason the division or multiplication of 2 numbers sometimes produces a result that appears wrong by a small amount.

When converting a double to an int you must anticipate this. You do this by allowing a margin of error.

A common way is to add a small value. For example

C++
steps = (position / half_angle) + 0.001;
 
Share this answer
 
v2
Floating point numbers can not accurately represent every real numbers, just a few of them. If you say for example d=1.333 then d will contain a floating point value that is near to 1.333 but isn't exactly 1.333 because it can not be accurately represented. The same is true to 0.1 and 0.9 and 1.8. This error is larger for values that are further from zero (either in positive or negative direction), the more digits you use in the whole part the less precision you have in the fractional part. Here we already have a small error and we did nothing with the number, just stored it as floating point. Imagine what happens if you have a lot of floating point values that already have a bit of error in the representation of the real numbers you want to use (like 1.8 and 0.9) and then you perform operations like addition, substraction, division,... These errors accumulate and with (random amount of) time they usually grow larger.

In this case a correct solution would be using integers (Fixed point arithmetic[^]).
Fixed point implementation: Fixed Point Class[^]
 
Share this answer
 
If you want to round to the nearest integer, add a value of 0.5 to the result before converting to an integer. If you want to round down, add a small value (e.g. 0.01 in your case).

The problem is that most rational numbers can't be represented exactly using floating point numbers. If you want to know more, you may start at the Wikipedia article on Floating point[^].
 
Share this answer
 
In such case, I think you should round number before converting them to integer.

In many cases, it might not matters much. You have taken an example where you are really near a "split" point. In practice, if you round every thing, then instead of having the problem for number that are a whole number, you will the problem when the result is near half step.

As other have mentionned, in some cases the beest way to avoid those problems is to uses fixed arithmetic. This could work well if you can uses a fixed resolution.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900