Decimal to fraction

Understanding the language, error messages, etc.

Decimal to fraction

Postby aderp1 » Tue Mar 24, 2015 1:06 am

Hello everyone,

I am making a game that involves angles, and I need to convert the output of the sine of an angle to fraction format. For example, when I do the sine of 30 degrees (0.523598... radians), the output is 0.5 radians and I need it to output 1/2. Does anyone know if there is a function for the conversion?
aderp1
 
Posts: 21
Joined: Sun Apr 27, 2014 7:24 pm

Re: Decimal to fraction

Postby Myndale » Tue Mar 24, 2015 6:19 am

This can't be done with perfect accuracy. Trigonometric functions are irrational, i.e. most have an infinite number of digits. Fractions, by definition, are not.

What you need to do is pick some arbitrary value for the denominator that's enough for whatever the application is e.g. 1024. The numerator is then just 1024*X rounded to the nearest integer, where X is your trig value. So in the case you gave the value of 0.5 would wind up as (0.5*1024)/1024 = 512/1024.

I suspect what you really want is some way of then converting that fraction into the smallest numbers that can be used to represent that same fraction which in this case is 1/2. To do that you need to divide both numerator and denominator by what's called the "greatest common divisor", which in this case is 512 (i.e. dividing 512/1024 results in 1/2). There are many algorithms you can used to find the GCD, Google is your friend here and the Wikipedia page on them also has plenty of examples:

http://en.wikipedia.org/wiki/Greatest_common_divisor

Obviously the choice of denominator is critical, 1024 will work terrific for powers of 2 but won't work as well as other values for (say) multiples of 3.
Myndale
 
Posts: 507
Joined: Sat Mar 01, 2014 1:25 am

Re: Decimal to fraction

Postby aderp1 » Tue Mar 24, 2015 8:49 pm

Thanks Myndale. I managed to figure it out. Here's the code:

Code: Select all
void moveAngle(int angle){
   double radian = ((atan(1)*4)/180 * angle);
   double toa = tan(radian);
   
   int denominator = 1000;
   int numerator = toa*denominator;
   int gcd;
   
   for(long i=denominator;i>0;i--){
      if(numerator%i==0 && denominator%i==0){
         gcd = i;
         numerator /= gcd;
         denominator /=gcd;
         break;
      }
   }
   int rise = numerator;
   
   int run = denominator;

   gb.display.print(rise);
   gb.display.print(F(" / "));
   gb.display.print(run);
}
aderp1
 
Posts: 21
Joined: Sun Apr 27, 2014 7:24 pm

Re: Decimal to fraction

Postby aderp1 » Wed Mar 25, 2015 12:35 am

Ugh, now the problem is trying to get the player to move along that slope at a specified speed. You can't just subtract the rise from the player's y and add the run to their x- some of the rise and run values are pretty high, and the player just flies off the screen. Any ideas?


Here's the code:
Code: Select all
void moveAngle(int &x, int &y, int angle){
   double radian = ((atan(1)*4)/180 * angle);
   double toa = tan(radian);
   
   double run = 10;
   double rise = toa*run;
   double runDecimal = run-int(run);
   double riseDecimal = rise-int(rise);
   int gcd;
   
   for(int i=run;i>0;i--){
      if(fmod(rise,i)==riseDecimal && fmod(run,i)==runDecimal){
         gcd = i;
         rise /= gcd;
         run /= gcd;
         break;
      }
   }
}
aderp1
 
Posts: 21
Joined: Sun Apr 27, 2014 7:24 pm

Re: Decimal to fraction

Postby Myndale » Wed Mar 25, 2015 3:29 am

Not quite sure I understand what you're trying to do here, if you simply want to move the player at a fixed speed in a given direction then you use cos() and sin() scaled by the speed:

Code: Select all
void moveAngle(float &x, float &y, int angle) {
   const float speed = 10;
   float radian = (angle*PI/180);
   x += speed * cos(radian);
   y += speed * sin(radian);
}


Note that I've also made x and y floats, to avoid jitter you should probably keep them as floats and cast them to integers when it's time to draw the object on screen.
Myndale
 
Posts: 507
Joined: Sat Mar 01, 2014 1:25 am

Re: Decimal to fraction

Postby jonnection » Wed Mar 25, 2015 11:36 am

You need fixed point math + sine/cosine lookup tables to really hit some speed.

http://sourceforge.net/projects/avrfix/
https://jfdube.wordpress.com/2011/12/06/trigonometric-look-up-tables-revisited/
User avatar
jonnection
 
Posts: 317
Joined: Sun May 04, 2014 8:21 pm


Return to Programming Questions

Who is online

Users browsing this forum: No registered users and 16 guests

cron