Two questions: 1. How do I calculate a "sign" with Arduino? 2. I have difficulties with fractions.
Question 1
How do I calculate the sign of a number?
e.g. Sign(-3)=-1
e.g. Sign(5)=1
I could use an equation like: (-3)/(sqrt((-3)*(-3))) but that would be time consuming. Is there a function avalable?
Question 2
Consider the following program
int Xcoord[]={12,17,23,25,22,29,33,32,35};
int Ycoord[]={15,13,16,20,23,26,22,19,15};
int xCount = 9;
int x;
int y;
int a;
int xx;
int yy;
float SlopePower2;
void setup() {
Serial.begin(9600);
}
void loop() {
for (int a = 1; a < xCount; a++)
{
int xx=Xcoord[a-1];
int yy=Ycoord[a-1];
int x=Xcoord[a];
int y=Ycoord[a];
SlopePower2=((y-yy)/(x-xx))*((y-yy)/(x-xx)) ;
Serial.print("SlopePower2 =");
Serial.print(SlopePower2);
Serial.println();
delay(5000);
}
}
//end
An Array is used to read numbers (this works fine).Then the power of the slope is calculated. Sometimes this number is larger than 1 (then the calculation works fine). However when the calculated value is between 0 and 1 ( a fraction thus) it is rounded off to either 0 or 1 (although I have assigned it as a "float"). Why?
26
answers
|
Answer it!
|
Steve
(I'm trying to build a robot for the contest).
It gets part of its input from a set of arrays X and Y (what I showed is part of the entire program). With this it has to calculate the slope and the distance between two points (x and y).
slope=dy/dx
distance=sqrt(dy*dy+dx*dx)
These are pretty basic equations, I don't think there is a alternative.
However, your comment has made me think of the following:
In the loop x and y are taken from the array's. Then dx and dy are calculated, then the slope and the distance are calculated (and some other stuff).
Would it be faster to to do the following?
In the setup() part of the program, quickly read the entire X and Y array and then fill a new Array with all the dx's, fill a new a Array with all the dy's, fill a new Array with all the new dy/dx.
In this way a large part of the calculation is kept out of the Loop(), making it faster (becaus in the Loop() only values of an Array have to be read instead of calculated).
Does this make sense? If so, how do I fill an Array that is a result of a calculation.
Do you need the sqrt calculation ? You could just work in distance squared units.
Steve
Do I need sqrt? I use Pythagoras to calculate the "long side"of a triangle (sorry for my English here). I could switch to Sin/Cos or Tan type calculations, but would this make it easier or faster?
Are you thinking of something else?
You have pointed out an algorithm that's been around since the sixties and I never heared of it. That's humbling (thanks!).
I'll have to study it closer though.
What about the idea of reading out the arrays in the Setup() phase. Would that help / work?
You could look at the potential values from your distance calculations, and use a look-up table.
Ask yourself (and tell me !!) what the practical resolution you need from your distance measurement is.
There are all SORTS of clever tricks you can do in an embedded system that aren't taught anywhere.
Steve
Practical resolution? If the Array is in cm, then I guess I need an accuracy of 2mm.
I'm very much interested in your ideas, but they are a bit "intimidating" as well. I have an idea for which I need to figure out a lot of stuff as it is:
1. The routines (currently discussing).
2. Getting the servos to work (in combination with the routine).
3. Building the mechanical parts.
If I introduce other algorithms (which I currently do not master) then my project becomes more complex. Maybe I should take the project as far as possible with "classic" algorithms and then come back to you for "the need for speed"?
We could eventually turn it into a collaboration if required...
100 cm ?
Personally, I would write a simulator program to evaluate my routines, before I built the rest of the machine a.) Because you can't break a program. and b.) The hardware may not match your final software !
Steve
I have done the calculations and graphs in Excell,
then I compare it to the output of the Arduino (by using a lot of Serial.print commands).
sign(double x) { return ((x>0)-(x<0)); }
where you take the numeric values of the bools, instead of conditionals.
I'm old-school and got too many other computer languages on the brain. In other languages sometimes FALSE is 0 and TRUE is Not 0 and not necessarily 1.
I didn't realise that in all implementations of C, boolean operators returning true is always return 1.
Thank you for improving my understanding!
Best Wishes
This is why you can write null-pointer checks in the form "if (!pointer) got-a-null-here;" Only the zero pointer will resolve that expression to true.
In FORTRAN, things are different, FALSE=0 still, but TRUE=-1.
sign(x) = +1 for x>0, 0 for x==0, and -1 for x<0
(I ignored the middle case). Doing a Web search, I found a beautifully compact representation, which uses the boolean numeric values (true=1, false=0) to compute the result without conditionals
int sign(double x) { return (x>0) - (x<0); }No but seriously, the effort is highly appreciated and for one, Í didn't know the answer in the first place.
I was surprised by the extreme compact suggestion you made. I have never seen it in the "classic" text books. Is this a variation of some kind?
You will find a lot of that stuff in more advanced textbooks, generally in discussions of code optimization. That's also where you're likely to find some of the really obfuscatory tricks like using bit-shift operations for specialized arithmetic, the use of "register" variables, and so on.
In Pascal
Sgn:=0;
IF number > 0 then sgn:=1
ELSE
if number <0 THEN sgn:=-1;
Besides, I didn't ignore the middle case, I decided to roll it into <0.....
Steve
So nothing stayed undefined :-)
Steve
int sign(double x) { return x<0 ? -1 : 1; }2) Your slope comes back as an integer because all of its operands are integers. Look at K&R, Chapter 2 (I think). If you want to compute a floating point ratio, you need to cast the operands to float:
SlopePower2 = float(y-yy)/float(x-xx);
SlopePower2 *= SlopePower2;
Note: Don't calculate the ratio twice; that's a waste of time. Also, take the declarations out of the loop; that's allocating extra and unused memory.
We know that only Chuck Norris can divide by zero. :-)
2.) You are dividing two integers in the maths, therefore the result is integer1 DIV integer2 and not /
Steve
![]() |


































