Multiply by a factor, precisely

Jeremy Leach

Senior Member
This is another version of my WordAWordBDivWordC routine, but simplified for use with any picaxe. Uses ~ 60 bytes.

It allows multiplication of a word value by a factor, without overflow, and gives an exact result expressed as a Whole and Remainder part.

For instance, the example I use in the code is converting between Knots and MPH. 1 Knot = 1.15077945 mph. So SpeedMPH = SpeedKnots * 1.15077945.

The factor value in my routine is expressed as WordB/WordC. To get the best accuracy in the results always use 65535 for WordB if the factor >1 and 65535 for WordC if the factor <1.

For example, if we know the factor needed is 1.15077945 then:
65535/WordC = 1.15077945. ie WordC = 56948

You can run this code in the sim and see the result (with serial panel active).

#picaxe 08m


This 60 byte routine exactly multiplies a Word value by a factor, giving a whole and remainder result.
The calculations won't overflow. It assumes the result is a single word.

Result = WordA * Factor, where Factor is WordB/WordC.

To see a detailed description of how this works see my WordAWordBDivWordC routine 
(this is a version for any picaxe). 

Set WordA, WordB and WordC.
Call MultByFactor.
The exact result is given in ResultWhole and ResultRemainder.

To get the greatest accuracy, always use extreme values. i.e if a factor>1 then express it as 65535/WordC.
Or a factor < 1, express it as WordB/65535.

Symbol WordA		= w0
Symbol WordB		= w1
Symbol LessThanWordC	= w1
Symbol WordC		= w2
Symbol ResultWhole	= w3
Symbol ResultRemainder	= w4
Symbol LSW			= w5
Symbol TempRemainder	= w5
Symbol MSW			= w6

'***TEST CODE*******
'This example shows how to multiply by a factor 1.1507 (65535/56952), which is the conversion of Knots to MPH. 
WordA = 201
WordB = 65535
WordC = 56952
Gosub MultByFactor
SerTxd ("ResultWhole = ",#ResultWhole,"  ResultRemainder = ",#ResultRemainder)


	ResultWhole = 0
	ResultRemainder = 0
		'Calculate the most and least significant words, resulting from WordA * WordB
		LSW = WordA * WordB
		MSW = WordA ** WordB
		'Add TermA to result
		ResultWhole = -1 / WordC * MSW + ResultWhole
		'Add whole part of TermC to result
		ResultWhole = LSW / WordC + ResultWhole
		'Calc TermC remainder value.
		TempRemainder = LSW // WordC
		'Calc how much ResultRemainder is currently less than WordC.
		LessThanWordC = WordC - ResultRemainder 
		'Prepare the new Remainder value.
		ResultRemainder = ResultRemainder + TempRemainder
		'But adjust the Whole and Remainder values if necessary.
		If TempRemainder >= LessThanWordC Then
			ResultRemainder = ResultRemainder - WordC 
			Inc ResultWhole
		'Load WordA and WordB
		WordA = - 1 // WordC + 1
		WordB = MSW
	Loop Until WordB = 0 'when the next iteration would give Whole and Remainder of 0.
Last edited: