Peter Bragg

14-Jun-2007, 11:11 AM

A couple of little functions that someone might find useful.

Sometimes you need to do a division calculation but end up losing something!

For example, divide 10 by 3 to 2 decimal places. You get an answer of 3.33.

Fine, I am not going to quibble with that, except that if you then do 3.33 x

3, you don't end up with 10, you end up with 9.99. You've lost 0.01!

This might not seem important but if you are dealing with larger amounts and

those amounts are for example financial figures your accountant may want to

know where the missing money is!

So here is a little division function that simply splits the passed value

into the specified number of 'equal' chunks but such that nothing goes

missing (- so not necessarily equal then). It returns an array of values

that will always add up to give you the number you started with.

The return values will be to the same degree of accuracy as the passed value

that we are dividing, with the exception that if the passed value is an

integer it will default to 2 decimal places.

So for example, 10 divided by 3 will return the 3 values 3.33, 3.33 and 3.34

where as 10.1 divided by 3 will return 3.4, 3.3 and 3.3. Here the return

values are only to 1 decimal place because that is equal to the number of

places in the number 10.1. You may decide that you always want to return a

fixed number of decimal places though - please feel free to change the code!

The function calls a rounding function so here are the 2. You may have (and

would prefer to use) your own rounding function though which is why it is

separate.

//RoundToN is simply a rounding function that rounds a number to the given

number of decimal places.

Function RoundToN Global Number nRounding Integer iDecPlaces Returns Number

Move (10^iDecPlaces) to iDecPlaces

Move (nRounding * iDecPlaces) to nRounding

Move (Round(nRounding)) to nRounding

Move (nRounding / iDecPlaces) to nRounding

Function_Return nRounding

End_Function

//DivideWithNoLoss returns an array of values that always add up to the

number you started with - so you don't lose anything.

Function DivideWithNoLoss Global Number nNumToDivide Integer iDivideBy

Returns Number[]

Number[] nResults

Number nResult

Integer iDecPlaces iPos

String sNumToDivide

Move (String(nNumToDivide)) to sNumToDivide

Move (Pos(".",sNumToDivide)) to iPos

If (iPos<>0) Begin

Move (length(sNumToDivide)-iPos) to iDecPlaces

End

Else Move 2 to iDecPlaces

Repeat

Move (nNumToDivide/iDivideBy) to nResult

Get RoundToN nResult iDecPlaces to nResult

Move nResult to nResults[SizeOfArray(nResults)]

Move (nNumToDivide - nResult) to nNumToDivide

Decrement iDivideBy

Until (iDivideBy=0)

Move (SortArray(nResults)) to nResults

Function_Return nResults

End_Function

So

number[] nResults

Get DivideWithNoLoss 11.002 3 to nResults

will give you: 3.667, 3.667 and 3.668. Add 'em all up again and you're back

to 11.002

I have had this function for a while and forgot all about it. It is not

rocket science but someone somewhere (other than us) might find it useful -

you never know...

Peter Bragg

Sometimes you need to do a division calculation but end up losing something!

For example, divide 10 by 3 to 2 decimal places. You get an answer of 3.33.

Fine, I am not going to quibble with that, except that if you then do 3.33 x

3, you don't end up with 10, you end up with 9.99. You've lost 0.01!

This might not seem important but if you are dealing with larger amounts and

those amounts are for example financial figures your accountant may want to

know where the missing money is!

So here is a little division function that simply splits the passed value

into the specified number of 'equal' chunks but such that nothing goes

missing (- so not necessarily equal then). It returns an array of values

that will always add up to give you the number you started with.

The return values will be to the same degree of accuracy as the passed value

that we are dividing, with the exception that if the passed value is an

integer it will default to 2 decimal places.

So for example, 10 divided by 3 will return the 3 values 3.33, 3.33 and 3.34

where as 10.1 divided by 3 will return 3.4, 3.3 and 3.3. Here the return

values are only to 1 decimal place because that is equal to the number of

places in the number 10.1. You may decide that you always want to return a

fixed number of decimal places though - please feel free to change the code!

The function calls a rounding function so here are the 2. You may have (and

would prefer to use) your own rounding function though which is why it is

separate.

//RoundToN is simply a rounding function that rounds a number to the given

number of decimal places.

Function RoundToN Global Number nRounding Integer iDecPlaces Returns Number

Move (10^iDecPlaces) to iDecPlaces

Move (nRounding * iDecPlaces) to nRounding

Move (Round(nRounding)) to nRounding

Move (nRounding / iDecPlaces) to nRounding

Function_Return nRounding

End_Function

//DivideWithNoLoss returns an array of values that always add up to the

number you started with - so you don't lose anything.

Function DivideWithNoLoss Global Number nNumToDivide Integer iDivideBy

Returns Number[]

Number[] nResults

Number nResult

Integer iDecPlaces iPos

String sNumToDivide

Move (String(nNumToDivide)) to sNumToDivide

Move (Pos(".",sNumToDivide)) to iPos

If (iPos<>0) Begin

Move (length(sNumToDivide)-iPos) to iDecPlaces

End

Else Move 2 to iDecPlaces

Repeat

Move (nNumToDivide/iDivideBy) to nResult

Get RoundToN nResult iDecPlaces to nResult

Move nResult to nResults[SizeOfArray(nResults)]

Move (nNumToDivide - nResult) to nNumToDivide

Decrement iDivideBy

Until (iDivideBy=0)

Move (SortArray(nResults)) to nResults

Function_Return nResults

End_Function

So

number[] nResults

Get DivideWithNoLoss 11.002 3 to nResults

will give you: 3.667, 3.667 and 3.668. Add 'em all up again and you're back

to 11.002

I have had this function for a while and forgot all about it. It is not

rocket science but someone somewhere (other than us) might find it useful -

you never know...

Peter Bragg