- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Is anyone reading this far?
In Perl, implementing the algorithm as described, showing working:
#!/usr/bin/perl -w
use strict;
my $a = shift or die( "need arg 1" ); my $b = shift or die( "need arg 2" ); my $neg = ($a < 0 xor $b < 0) ? -1 : 1; my @nums; for ($a = abs $a, $b = abs $b; $a > 0; push(@nums,{'a'=>$a, 'b'=>$b}), $a >>= 1, $b <<= 1) {} map {print "$->{'a'} + $->{'b'}\n" } @nums; print( "###\n" ); @nums = grep {$->{'a'} % 2} @nums; map {print "$->{'a'} + $->{'b'}\n" ;$a += $->{'b'} } @nums; print( 'sum: ', $a * $neg, "\n" );
Admin
A Python solution. It could definitely be done in less code, but I'd rather be able to understand it.
Admin
Pretty similar in C;
int l(int l1, int ll) { return l1&-2?l1%2ll+l(l1/2,ll2):ll; }
Looks kind of like a traffic accident, doesn't it?
Admin
I didn't check to see if there was an F# one done yet or not. But here is my attempt.
Admin
I was disturbed by the fact that the Perl uses the multiplication operator when it doesn't need to, so I offer:
Or, moderately golfed:
Or, from a slightly different angle:
Admin
python. Gratuitous use of list comprehensions and generators. Doesn't work for negative numbers. Patches welcome ;-)
Admin
fun pmulti 1 r t = t + r | pmulti l r t = pmulti (l div 2) (r * 2) (t + r * (l mod 2))
pmulti 3 4 0 will give you 3 * 4, t is just an accumulator
Admin
In Python:
a,b = 190, 232 if a<0: a=-a; b=-b print sum([b<<s for s in xrange(0,int(math.log(a,2)+1)) if ((a>>s>0) and ((a>>s)%2)) ])
Admin
Admin
(Readable) Ruby version Handles negative numbers (and unlike some of the examples i read, returns correct signs)
Admin
For maximum speed, I pre-allocate the tables I use for storage, and avoid all floating-point multiplies and divides. A complete executable program in Lua; run with an argument (any argument) for the peasant-product, without to use the baseline-for-testing "Gold" function.
Admin
As a circuit diagram
[image](Handles 4-bit unsigned integers)
The selection of input wires for AND gates perform the right shifts. The AND gates perform the oddness test. The selection of input wires for the adders perform the left shifts.
Addendum (2009-07-22 23:27): I forgot to mention this was done in MS Paint
Admin
Take your pick:
Admin
Speccy basic, recursive:
Admin
Originally I thought about sending 1235th boring C# version or 436th Python version but then I realized that there is no GUI version (except for few PHP or JS versions with HTML WUI [Web User Interface :-) ]). So I created one using my all-time favourite library: Turbo Vision (so it's really TUI and not GUI). Tested with BP7 and recent FreePascal.
Addendum (2009-07-22 21:05): Download (Source+binaries for DOS and Windows)
Admin
#!/usr/bin/env python
def rus_mult(A, B): if A == 1: return B else: return rus_mult(A / 2, B * 2) + (A % 2) * B
def run_tests(): tests = [(18, 23), (12, 3), (1, 1), (15, 2), (8, 22), (7, 13), (9, 20)]
if name == "main": run_tests()
Admin
C#, handles negative numbers 0, 1.
And, as usual, the most elegant solution is the recursive one.
Admin
theres some ruby code for you
Admin
Here's one in Motorola 68000 assembly:
Note that this one is actually useful, it can be used if you don't have a working libgcc for your target. :-) Though that one is faster. ;-)
That said, on CPUs like the Z80 which don't have a native multiplication instruction, Russian Peasant is actually extremely useful.
Admin
def Mul(a,b): return DirectionsFromLeaders( "mul", a, b )
example:
Admin
My Perl-solution with optimization, a bit of math and several tests. It also handles negative numbers.
Admin
Admin
Admin
In c#
Handles 0, negatives, and optimizes which digits to place in which column.
And. Fast.
Addendum (2009-07-23 13:39): Whoops, that should have been:
Admin
Bah, one-liners. I figured I'd write my code in true WTF style.
Admin
Two PHP functions in there: the first one does the maths, the second one displays a (very) barren page detailing the steps.
Fun :-) Syntax highlighting was just ... too much free time ;)
Admin
Admin
$ perl -E'($i,$j)=@ARGV;while($i){($i!=int($i/2)2||!int($i/2))&&($k+=$j);$j=2;$i=int($i/2)}say$k' 18 23 414 $
Admin
Here's my code in python:
Admin
I'm a little disappointed that I haven't seen any submissions in the language actually used to perform Important tasks involving numbers: COBOL.
Tested with OpenCobol 1.0.
Admin
Or shorter : $ perl -E'($i,$j)=@ARGV;while($i){($i%2||!$i/2)&&($k+=$j);$j*=2;$i=int($i/2)}say$k' 18 23 414 $
Admin
IMO, the peasants aren't actually multiplying and dividing by two, rather, they're doubling and halving numbers, a less generic but far simpler operation, that's why using * and / is cheating.
Anyway, some more Haskell. This one handles negative numbers (don't think any Haskell entry so far does that,) is tail recursive AND uses type classes!
Admin
Oops, that second | a < 0 ... should be | b < 0 ...!
Admin
Updated from earlier post that I never bothered to updeate correctly.
done in wonderful VBA, and just like in the article, shows full manual working out table in the debug window. Works with negatives, zeros, hopefully everything really. I stuck to the principle and process of the manual process instead of taking shortcuts.
Sample output
Admin
package test;
import java.util.ArrayList; import java.util.List;
public class RussianMultiplication {
}
Admin
Another Oracle SQL Example:
Admin
In Python, aiming for readability.
Admin
How about a good dose of OOM?
The code's too long to post here, but beyond this link you can enjoy it in fully highlighted PHP syntax: http://justas.ggcmedia.com/MultiplicationFramework.html (usage example at the end of the file)
Sample output:
...hmm, I need to go clean my hands now.
Admin
int mul_rus(int a, int b) { int c = 0;
}
Admin
Here's a fairly straightforward implementation in common lisp:
It could be all on one line, but that'd be harder to read. If someone has suggestions on how to simplify it, that'd be great. :)
Admin
In PDP-8 assembly language. Untested
X, 0 Y, 0 Z, 0
RUSMUL, 0 // entry point CLA DCA Z / clear total
LP, TAD X SNA JMP DONE
DONE, TAD Y TAD Z JMP I RUSMUL
Admin
Sloppy JS version with animated step-by-step output: http://crindigo.com/stuff/praxis.html
Admin
Uses NO math operations, only regex and string operations. Almost all major work is kept in the global $_ variable. Numbers are represented internally using a base-30-like system, then converted directly back to decimal at the end of each operation. Some assumptions about collating sequence were made (e.g. \d == [0-9]).
Admin
--SQL Server using Common Table Expression
DECLARE @number1 int; DECLARE @number2 int;
SET @number1 = 18; SET @number2 = 23;
WITH Multiplication (Row, Factor1, Factor2) AS ( SELECT 1, @number1, @number2 UNION ALL SELECT Row + 1, Factor1 / 2, Factor2 * 2 FROM Multiplication WHERE Factor1 > 1 ) SELECT SUM(Factor2) FROM Multiplication WHERE Factor1 % 2 = 1;
Admin
func(a, b): if(a == 1) return b if(a%2 == 1) return b2 + func(a/2, b2) else return func(a/2, b*2)
Had to do it with recursion. I can't think of a reason why not to do it that way. I also haven't looked at the comments. Someone probably came up with this solution or it has already been shown to be wrong. I could also shrink it to be a single line but then it wouldn't be nearly as readable.
Admin
--It works better as a stored procedure
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Paul N -- Create date: 7/22/2009 -- Description: multiplies two numbers using -- Russian Peasant Multiplication -- ============================================= CREATE PROCEDURE dbo.[Russian Peasant Multiplication] -- Add the parameters for the stored procedure here @number1 int, @number2 int AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON;
END GO
Admin
open List
let oddcar (n, _) = (n land 1) = 1 let sum = fold_left (+) 0
let rec do_mul = function | (x,_) :: _ as lst when x == 1 -> sum (map snd (filter oddcar lst)) | (x,y) :: _ as lst -> do_mul ((x / 2, y * 2) :: lst)
let mul x y = do_mul [x,y]
Admin
C# + LINQ
Addendum (2009-07-23 01:23): More LINQ-ish:
Admin
simple erlang:
Admin