# Division by a fraction in assembly

#### Peet19

##### Member
Hi everyone!
I would like to know how to divide by a fraction in assembly?
Eg: 18 / 4.1
Here the result is 4.39.
I want to put the whole number (4) in one register and the fractional part (39) in another register separately.
How can this be solved?

Solution
So the 18F24K22 does have a hardware multiplier, but you did not specify if any of the numbers was a constant or not.

Using your numbers 18 and 4.1 ... As an example if 4.1 is a constant, then the multiplicative inverse is 1/4.1 or 0.2439 ... so take 0.2439 and multiply by 1000 and round up so it becomes 244

244 x 18 = 4392 ... now since you multiplied by 1000 before... divide by 1000 here (or just shift the decimal) and your answer is 4.39

Since the 18F24K22 has a hardware multiplier just do this in code...

movlw 244
mulwf 18

Hi everyone!
I would like to know how to divide by a fraction in assembly?
Eg: 18 / 4.1
Here the result is 4.39.
I want to put the whole number (4) in one register and the fractional part (39) in another register separately.
How can this be solved?
You do the operation with a pair of integers and scale the result. 18/4.1 is the same as 180/41, except it is larger by a factor of 10. You don't have to do the scaling in decimal, it can be done in binary, which just involves shifting.

Thank you, what you wrote is true, but the result will still be a fraction. In other words, the fractional part is discarded by the compiler and only the whole remains, but I also need the fractional part.

If you look on the PICLIST (while it still exists) there are floating point maths routines in assembler.

Thank you, what you wrote is true, but the result will still be a fraction. In other words, the fractional part is discarded by the compiler and only the whole remains, but I also need the fractional part.
No that is not necessarily true. You can do fixed point integer operations in assembler as long as you keep track of where the binary point is. You did not say you were interested in floating point operations. It makes a big difference.

• rjenkinsgb
Are any of your values constants? ... If so, then if you are tricky you can use multiplication by using the multiplicative inverse of the constant. You did not say which processor you are using. Some have a built in hardware multiplier.

• rjenkinsgb
assuming you can do 16 (or 32) bit division, multiply the top number by 100 + 10 times the number of decimal places you need, the bottom number by 100.
This will give (in your example) 180000/410 which is 439 and somert.
Split it into the two parts, 4 and 39.
Depending on your numbers, this could be simplified - 18000/41 will give the same result.

Mike.

The most basic question, is how are you representing the non-integer numbers?

The simplest approach for fractional math throughout a program is a fixed-point implementation - eg. I've used 16 bit integer + 16 bit fraction, so 32 bit storage with the "point" in the middle.

Then treat it as a normal integer, but working with units of whatever fraction suits the point position, so 1/65536 for that setup.

Allow 16 bits to the left for multiply and 16 bits to the right for divide for result storage, to make up for the fractional offset that will need byte-shifting to correct the results.

Treat the integers as if multiplied by 65536, so your original division would become 1,179,648 / 268,698

Use however many bits for the integer and fraction parts to get the range and precision you need in your application, eg. 8+8 if that's enough, with units or 1/256

(That was the basis of something I wrote in the early 80s, for machine tool controllers. The measuring systems were resolver based and after conversion gave units of 1/32768 inches, so one "spare" bit in the storage).

Thanks for the replies everyone.
The multiplication by 100 method worked.
I don't understand this fixed point calculation.
How to track the location of the binary point?
18F24K22

Thanks for the replies everyone.
The multiplication by 100 method worked.
I don't understand this fixed point calculation.
How to track the location of the binary point?
18F24K22
When I do fixed point I just use 100 or 1000 that way I've two or three decimal places.
But as JRW said , when you have to work with precision the bigger the number the better the resolution.

512 * 500 / 1024 = 250 or 2.50 once the decimal is in place..
this gives 0.005v resolution ( 0.0488v really)

Note the 500 is the key here. 5.00 two decimal places.

For fixed point, the results for addition and subtraction are not affected.

For multiplication, the result is offset by (thinking again about it) twice the bit offset you are using for the fraction.

eg. Think of it as if you were working with inches to thousandths; the total number is in thous.

1.000 x 1.000 inches becomes 1000 x 1000 thou, so the result will be offset by six places, twice the fraction offset.

No extension or shift is required for division as it's still the same ratio, but you may want to use extra fractional bits if you are doing large numbers of successive calculations, to avoid accumulative rounding errors.

For binary 16.16 multiplication, the result would be 32 bits in the high part of an (imaginary or temporary) 64 bit value, so still 32 bit with the correct offset if you discard the lower 32 bits of the result.

ps. I always try to use power-of-two ratios or factors with maths such as this rather than decimal, as that means the conversions can be done easily by bit shifts rather than needing further multiplications or divisions.

Thanks for the replies everyone.
The multiplication by 100 method worked.
I don't understand this fixed point calculation.
How to track the location of the binary point?
18F24K22
You just do it in your head - it's dead simple to keep track of - you're only usually talking about 100's or thousands.

Think of it as doing maths on money - convert everything to pennies (or cents) rather than pounds (or dollars), do the maths, then convert it back to pounds (or dollars) if you need to.

I usually do it in the integer to string conversion routines.

So the 18F24K22 does have a hardware multiplier, but you did not specify if any of the numbers was a constant or not.

Using your numbers 18 and 4.1 ... As an example if 4.1 is a constant, then the multiplicative inverse is 1/4.1 or 0.2439 ... so take 0.2439 and multiply by 1000 and round up so it becomes 244

244 x 18 = 4392 ... now since you multiplied by 1000 before... divide by 1000 here (or just shift the decimal) and your answer is 4.39

Since the 18F24K22 has a hardware multiplier just do this in code...

movlw 244
mulwf 18

Very good ideas. Thank you so much everyone, I learned a lot.  