Fixed point math is a method of carrying a fraction within an integer. For example, a ledger, based on a major currency containing 100 of the lowest coin value, could have all its entries without the decimal delimiter. Using the US dollar as example, an entry of 2458 would be interpreted as meaning $24.58 since the last two digits would have been designed as being a fixed fractional portion.
The same principle can be applied to binary numbers. Using a 32-bit dword, the last 8 bits could be defined as being the fractional portion. Based on such definition, a value of 1.0 would then be represented in binary as:
00000000 00000000 00000001 00000000
Dividing the above number by 2 would yield:
00000000 00000000 00000000 10000000
which would then be equal to 0.5 in decimal notation. Dividing by other multiples of 2 will give you an appreciation of the value of each bit of the fractional portion. The least significant bit would then be equal to 1/256 or approximately 0.004 in decimal notation.
Negative numbers can also be allowed as long as the most significant bit is not used for the "integer" portion of the number. Such fixed point numbers can then be added or subtracted directly without loosing any of their precision if there is no overflow of the integer portion.
Multiplications and divisions can also be performed on such numbers but some precautions must be taken. For instance, the result of a multiplication would contain twice the number of fractional bits. Half of them would need to be shifted back out to obtain a result in the same format as the multiplication operands.
Compare that to a decimal multiplication of 3.74*2.12 without the decimal delimiter. The result would be 79288. Shifting out the last two digits and rounding would give the correct result: 793. There will generally be some loss of precision with multiplications unless the fractional portion of one of the operands is 0.
You can also observe that a fixed point number could be multiplied directly by a real integer without the need for a correction. For example with decimal numbers, multiplying 3.74 by 6 without the decimal delimiter yields 2244 which has the correct format.
Before performing a division, the number being divided must contain twice the number of fractional bits as the base format. Again, using a decimal example, dividing 3.74 by 2.12 without the decimal delimiters would yield 1 which would not have the correct format. Two 0's would first have to be appended to the 374 before performing the division by 212. The result would then be 176 and become 1.76 when converted with the decimal delimiter.
As for multiplications, a fixed point number can also be divided by a true integer without the need to pre-adjust its number of fractional bits. You can verify that easily with decimal numbers.
As a side note, the IEEE floating point format could be compared to a fixed point format. The main differences are that only the most significant bit is retained for the "integer" portion and a biased exponent of 2 is part of the format. It could be related to the scientific notation format for decimal numbers.
A library of functions for fixed point math has been prepared. It is based on using the lower 16 bits of a dword for the fractional portion. This allows a range of +/-32767 for the integer portion and an accuracy equivalent to approximately 0.00002 for the fractional portion. The zipped file contains:
- the library itself,
- the source code for each of the functions,
- a Help file,
- a small dialog box program to compare the result of the functions with those obtainable with the FPU,
- one example program using fixed point math for drawing a sinusoidal curve based on user input,
- one example program to compute the value of the Napierian constant accurate to 8 decimal places.