The Daily WTF posted a challenge to code the Russian Peasant Multiplication. Here’s mine:

Function RussianPeasant(lFirst As Long, lSecond As Long) As Double

Dim lDiv As Long

Dim lMult As Long

Dim lMod As Long

lDiv = lFirst

lMult = lSecond

Do Until lDiv = 1

Debug.Print lDiv, “x”, lMult

If lDiv Mod 2 = 1 Then

<strike>lMod = lMult</strike>

lMod = lMod + lMult

End If

lDiv = lDiv 2

lMult = lMult * 2

Loop

Debug.Print lMult, “+”, lMod

RussianPeasant = lMult + lMod

End Function

Dim lDiv As Long

Dim lMult As Long

Dim lMod As Long

lDiv = lFirst

lMult = lSecond

Do Until lDiv = 1

Debug.Print lDiv, “x”, lMult

If lDiv Mod 2 = 1 Then

<strike>lMod = lMult</strike>

lMod = lMod + lMult

End If

lDiv = lDiv 2

lMult = lMult * 2

Loop

Debug.Print lMult, “+”, lMod

RussianPeasant = lMult + lMod

End Function

The backward division sign means integer divison. I checked the first BASIC entry in the comments and it was done in five lines. Clearly I have some variable declarations, debugs, and white space that he doesn’t, but reading his code caused me to think about the problem in a slightly different way. He just aggregates lMult every time lDiv is odd, whereas I do the same thing just not as concisely.

This guy did it in one line. I’ll post a spreadsheet formula solution tomorrow.

Something looks wrong with your function… have you tested RussianPeasant(99, 100) ?

Dick – your code doesn’t always give the right answer. The line:

lMod = lMult

should be

lMod = lMult + lMod

Here’s my effort:

Function RPMult(Num1 As Long, Num2 As Double) As Double

Do While Num1 >= 1

If Num1 Mod 2 = 1 Then RPMult = RPMult + Num2

Num1 = (Num1 2)

Num2 = Num2 * 2

Loop

End Function

I made Num2 a double so it didn’t overflow so quickly.

I’ll be intrerested to see the worksheet approach (I had a think about it, but my brain crashed).

The best I can do…

Array formula in Excel:

=SUM(IF(MOD(INT(G9/2^(-1+ROW(INDIRECT(“1:”&CEILING(LOG(G9)/LOG(2),1))))),2)=1,G10*INT(2^(-1+ROW(INDIRECT(“1:”&CEILING(LOG(G9)/LOG(2),1)))))))

where G9 and G10 contain the numbers to be multiplied.

and in VBA

Function RussianPeasant(ByVal Int1 As Long, ByVal Int2 As Long) As Long

If Int1 = 0 Or Int2 = 0 Then Exit Function

Dim SignMult As Integer: SignMult = Sgn(Int1) * Sgn(Int2)

Int1 = Abs(Int1): Int2 = Abs(Int2)

Do

RussianPeasant = RussianPeasant + IIf(Int1 Mod 2 = 1, Int2, 0)

Int2 = Int2 * 2: Int1 = Int1 2

Loop Until Int1 = 0

RussianPeasant = RussianPeasant * SignMult

End Function

I’ve tried doing this in a plain spreadsheet (and I’m not that great at maths so I may have missed something), but it seems to only work if the number being divided is even. It gets the wrong answer if it’s odd.

So 19 * 23 comes out using this method:

19X23=437

94646

492

2184

1368368

414

Have I misunderstood this completely?

Lizz,

You have missed the other odd element in the list.

It decomposes to

1923

946

492

2184

1368

so you add all of the odds, 368+46+23. You seem to have missed the starting element which is also odd.

Yeah, I was thinking that the first number would only be odd once. But that’s clearly not true. I have no excuse as I was sober when I wrote this post.

Ah, that makes sense, thank you :o) I hadn’t realised the original numbers were included.

Spreadsheet formula.

=A1*B1

If you have a modern spreadsheet, absolutetly no need to conform to the old ways.