FUNCTION:  ProductDigits().  Pass an integer to this function and it will separate out each digit in the integer, multiply them all together, then return their sum. This is one of those functions that are so short you may be tempted to ask why not just put the code in the main routine and save the effort? There are two very good reasons.

Firstly, you may need to repeat this operation many times over from different parts of your program. Having a function means it only has to be typed into the code once. In addition, if you type the function in without error, it is always right. But if you have to type it into several parts of your program, a new opportunity for typos arises each time.

Secondly, it makes for neat top-down programming. The main routine can just say something like: sum = SumDigits(n). It's immediately clear to even an untutored reader what's going on, an uncluttered appearance is maintained, and the main routine is physically much shorter, making a visual overview much easier.

It's up to you what data type you make the argument, depending on the type of integer you want to process.


Exponent of 2

int 230 1073741824
uint 231 2147483648
int64 261 2305843009213693952
uint64 262 4611686018427387904

Declaring the function must be done like this:

declare ProductDigits(p: int) (or whatever integer type you want).

Here's the code:

sub ProductDigits(p)
' Returns the product of the
' digits of integer p. Will
' give incorrect answer if p
' larger than defined limits
' for integers.
def tot: int
tot = 1
    ' separate out LSD and totalise
    tot = tot * (p % 10)
    ' chop off LSD
    p = p/10
until p = 0: ' all chopped off!
return tot

There's only one local variable in this function: tot, my abbreviation for total. It's initialised to 1 before the calculation begins. The function's argument is p. All the action takes places in a four-line, two-instruction DO loop.

The line
tot = tot * (p % 10) is integer arithmetic. It means "take the remainder of dividing p by 10 and multiply it by the running total stored in tot. Place the result in tot, overwriting whatever is already there." If p is, say, 12345, then p divided by 10 will be 1234 remainder 5. The 5 is the bit we want. It's multiplied by the total and thus stored there. We have effectively multiplied the LSD (least significant, or rightmost, digit) by tot.

The line
p = p/10 means "change the value in p to be equal to p/10." If p is 12345, the new value will be 1234.5, won't it? No! The original declaration defined p as an integer, a number with no decimal part.  So the decimal part is dropped, and we end up with 1234. This has effectively lopped off the LSD.

The code now reaches the end of the DO loop. It needs to decide whether to execute the loop again, or just move on to the next instruction.

The line
until p = 0 is the decision-maker. If the last time we processed p it was only one digit long, executing p/10 would reduce it to zero. At that time all processing must be finished, and no more executions of the loop are necessary. This last instruction recognised that condition. It can be paraphrased as "Execute the DO loop again unless p equals zero."

The final line
return tot returns whatever value has accumulated in tot to the calling routine. In the case above, where p contained 12345, the function returns (1 * 2 * 3 * 4 * 5) = 120 to the calling routine.

Earlier versions of this function used strings, but I have found this method, using integer arithmetic, is much faster.


Site design/maintenance: Dave Ellis E-mail me!
Last Updated: March 27th, 2005.