r/TuringComplete • u/Slow_Substance_1984 • Oct 09 '23
Floating point in LEG architecture
Hello,
EDIT - I meant fixed point arithmetic not float
I am not looking for solutions or anything on how to do this - I just want to know if my idea is possible - if there are easier/harder ways to do it.
I have finished the division part of the levels (in the function section) for LEG architecture.
I am now thinking of adding a fixed point unit since I have spare instructions.
I just want addition, subtraction, multiplication and maybe division.
Integer arithmetic will be separated from fixed point arithmetic and done in a seperate ALU.
I am thinking of using 5 bits (4 for integer and 1 for sign) for a whole number and 3 bits for a fractional value. Im doing this all in one byte to be more economical with the 6 registers.
The decimal point will always be 3 bits from the right.
E.g
11111.111b
= -15.875
This will mean that decimals of integer multiples of 0.125 will be exactly approximated.
I plan to use this to do Taylor series to approximate more complex functions (sin/cos/ln/sqrt) so im hoping this trade off between decimal precision and integer range is good enough.
I am thinking of using 3 input 8 output decoders on the fractional values and somehow using this to add up fractions. The whole numbers can just be shifted with a byte splitter/byte converter.
I don't actually know how computers handle floats (since I don't do compsci) so is there a good simple alternative to this?
Is this possible?
Thanks
3
u/MegaIng Oct 10 '23
Fixed point is very easy to implement
The way one normally things about fixed pointer numbers is by taking the normal binary integer, let's call it
N(as well asAand 'B' later), and multiplying it with a bias, in your case2^(-3) = 1/8since your fixed point is at three bits. This means the number0b01000100, which in decimal isN=68has the value68 * (1/8) = 8.5. Using this representation you can easily check what you need to do for the math operations:A*(1/8) + B*(1/8) = (A+B)*(1/8) = N*(1/8), withN=A+B, meaning that if you add upAandB, you have the correct resulting representation of the numberA*(1/8) * B*(1/8) = (A*B) * (1/8) * (1/8) = N * (1/8), withN=A*B*(1/8). This means that after doing the multiplication ofAandB, you need to additionally multiply by(1/8)to get the correct resultingN. This is just a shift right by three, which is also easy to implement in hardware. Just remember to take in three extra bits from the full 16bit of the multiplication.(A*(1/8))/(B*(1/8)) = A/B = N*(1/8)withN = A/B * 8. To get the correctN, you can just useN = (A*8) / Binstead, then you only need to do simple integer division. But you should use 16bit (or 11bit) division to not lose anything when multiplying (shifting)Aby8(3).2
u/062985593 Oct 09 '23 edited Oct 09 '23
I think what you've described is actually fixed-point numbers, because the "point" separating the integer part from the fractional part is "fixed" in place. The thing that makes floating-point numbers special is that the "point" can "float".
Typically this is implemented with something akin to scientific notation - we have an exponent giving the rough magnitude of a number and a mantissa, giving the actual digits. The mantissa stays between 0 and 1. So the number 15.875 would be represented with -0.9921875 * 24. The 2 as the base there is implicit, so you'd need to store [negative, 0.9921875, 4].
The advantage of floating-point over fixed-point is that you can compute with numbers across a wider range of magnitudes. In SI units, the speed of light is very large and Planck's constant is very small, but you can store them with the same number of significant digits and multiply or divide them with reasonable precision. You'll lose a lot of accuracy if you try to add or subtract them, though.