How To: Make a 2D wave simulation Part 3


Fixed point arithmetic

Remember when I told you that everything is a representation of integers in the computer? Well in this page, I'm going to show you a genius way to represent decimal numbers using integers more efficiently than floating point arithmetic!

Suppose you want to multiply two decimal numbers, for example 0,5 with itself. Normally what you would do is 5 * 5 = 25, then divide by 100 to have 0,25. That's essentially fixed point arithmetic!
You can represent fractional numbers as an integer representation and imply that part of it is the integer part and a part of it is the fractional part! For this particular example, we can represent 1,5 as 15000 and define that the part of that number that's less than 10000 is the fractional part! Therefore, the 10000 represents 1, and 5000 represents 0,5.

Why though?

Because everything involving decimal notation and precision is simple! Using only integers!!!
Adding 15000 and 5000 equals 20000, which represents 2. Subtracting 5000 equals 10000, which represents 1. It makes sense!
Multiplication and division works the same way you would do 0,5 * 1,5 for intance.
Doing 15000*5000 equals 75000000. As you would do with real decimals, you have to divide by what represents one in this case, so 10000. Therefore, dividing the result with "one" gives 7500, which represents 0,75 -> exactly what 1,5*0.5 equals in real numbers!
Doing 15000/5000 gives 3. Multiplying that with the "one" (10000) gives 30000, which represents 3. Pretty cool huh?


Using it in computers

First of all, dividing, or multiplying, with 10n essentially shifts the number to the right, or to the left respectively. This works in every number system, including binary, which is what the computer understands! And best of all, there is a dedicated function for that!!!
This is the bit-shift operator! a >> 3 shifts the number a by 3 binary places to the right, essentially dividing with 23. a << 3 shifts the number a to the left by 3 places, multiplying it with 23.

With that being said, we can define a unity, let's call it ONE, which represents the value 1, in binary! Then, define the EXP or exponent, the number of places that make up the decimal part! So ONE is 1 << EXP! And finally, we're gonna define two functions, mulf and divf, that quickly divide and multiply numbers in this fixed point arithmetic. Now, you have a system that is more efficient than floating point arithmetic!


Putting it all together

Let's define the EXP, or precision if you will, as 12 binary places. This is important because we need a large precision factor for this simulation, or else it might break!
The full code for floating point arithmetic will therefore be:

#define EXP 12
#define ONE 0x1000 //one with 12 binary places

int mulf(int a, int b) {
  int res = a * b;
  //for a right bit shift, you have to handle the cases where result is negative
  if (res < 0) return -(-res >> EXP);
  return res >> EXP;
}

//NOTE: This function will not be used in the simulation, because division can be done with mulf anyway!
int divf(int a, int b) {
  return (a << EXP)/b;
}


This is basically everything we need! In the next page, I'm going to show you how to generate actual images!


Previous page Back Next page