- 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
in C# public int RussianMultiply(int operand1, int operand2) { int res = 0; while (operand1 > 0) { if (operand1 % 2 == 1) res += operand2; operand1 /= 2; operand2 *= 2; } return res; }
Admin
Yet another Scheme solution
;;proper R5RS (define (rusmult a b) (cond ;;special cases ((= a 0) 0);; okay, it's dirty, but i'm way to lasy ((= b 0) 0);; to try to come up with something better ((negative? a) (* -1 (rusmult (* -1 a) b))) (else (if (= a 1) ;; real computation (+ (if (odd? a) b 0)) (+ (if (odd? a) b 0) (rusmult (if (even? a) (/ a 2) (/ (- a 1) 2)) (* b 2)))))))
Admin
Recursive in C# public int RecursiveRussianMultiply(int operand1, int operand2) { return operand1 == 0 ? 0 : RecursiveRussianMultiply(operand1 / 2, operand2 * 2) + (operand1 % 2 == 1 ? operand2 : 0); }
Admin
C# solution (boilerplate not included)
private static List<Pair> _pairs = new List<Pair>(); private static void RussianPeasant(int a, int b) { _pairs.Add(new Pair(a, b)); if (a == 1) { int result = 0; foreach (Pair pair in _pairs) { if (pair.FirstNum % 2 != 0) result += pair.SecondNum; //accumulate all second nums, if first num in pair is an odd number } DisplayMessage("Result: " + result.ToString()); } else { //tail recursive call RussianPeasant(a / 2, b * 2); //half first number (ignoring remainder), double second number } }Admin
Scheme
(define (mult a b) (cond ((= b 1) a) ((= (remainder b 2) 1) (+ b (mult (* 2 a) (quotient b 2)))) (else (mult (* 2 a) (/ b 2)))))
not tested CAPTHA: vereor
Admin
Recursive C# in one line :)
private static long m(long f, long s) { return ((f&1)==1?s:0)+(f>0?m(f>>1,s<<1):0); }
Ok, it's just like the perl sample. Here, how it should be read:
private static long m(long f, long s) { return ((f&1)==1?s:0)+(f>0?m(f>>1,s<<1):0);
}
And for the whole "I can do it in a few chars" thing, from the return to the colon it's only 43 characters.
Admin
An ABAP solution that compiles:
REPORT MULTIP. DATA: product TYPE i, left_num TYPE f VALUE 18, right_num TYPE f VALUE 23, half_left TYPE f, half_left_floor TYPE f. WHILE left_num > 0. "check for even number and add to product (there must be a better way...) half_left = left_num / 2. half_left_floor = FLOOR( left_num / 2 ). IF half_left <> half_left_floor. product = product + right_num. ENDIF. "move to next set left_num = FLOOR( left_num / 2 ). right_num = right_num * 2. ENDWHILE. WRITE product.Admin
ugh, i meant it that way
;;proper R5RS (define (rusmult a b) (cond ;;special cases ((= a 0) 0);; okay, it's dirty, but i'm way to lasy ((= b 0) 0);; to try to come up with something better ((negative? a) (* -1 (rusmult (* -1 a) b))) (else (if (= a 1) ;; real computation (+ (if (odd? a) b 0)) (+ (if (odd? a) b 0) (rusmult (if (even? a) (/ a 2) (/ (- a 1) 2)) (* b 2)))))))Admin
This is going to get lost in the mix, but here's my take.
Note: I'm betting that most of the naive implementations people have done don't function correctly when multiplying negative numbers. This one does.
using System; using System.Data; using System.Diagnostics; using o = System.Console; // to compile on any modern Windows machine: // // PATH=%PATH%;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 // csc rusmult.cs class X { public static void Main(string[] args) { try { if (args.Length != 2) { o.WriteLine("Usage: {0} n1 n2", Environment.GetCommandLineArgs()[0]); return; } // doing this makes negative numbers work uint n1 = (uint)Convert.ToInt32(args[0]); uint n2 = (uint)Convert.ToInt32(args[1]); // ensure n1 < n2 to minimize steps if (n1 > n2) { n1 ^= n2; n2 ^= n1; n1 ^= n2; } int dig1 = (n1==0) ? 1 : (int) Math.Ceiling(Math.Log10(n1)); int dig2 = (n2==0) ? 1 : (int) Math.Ceiling(Math.Log10(n2)); int dig3 = dig1 + dig2; string fmt1 = string.Format("{{0,{0}}} x {{1,{1}}} ", dig1, dig3); string fmt2 = string.Format(" | + {{0,{0}}}", dig3); string fmt3 = string.Format("{{0,{0}}} x {{1,{1}}} = {{2}}", dig1, dig3); uint accum = 0; while (n1 > 0) { o.Write(fmt1, n1, n2); if ( (n1 & 1) != 0) { o.Write(fmt2, n2); accum += n2; } else { o.Write(" | strike"); } o.WriteLine(); n1 >>= 1; n2 <<= 1; } o.WriteLine(new string('-', dig1 + 3 + dig3 + 5 + dig3)); o.WriteLine(fmt3, args[0], args[1], (int)accum); } catch (Exception ex) { o.WriteLine("Error: {0}", ex); } } }Admin
Function PeasantMultiply(x As Integer, y As Integer) As Integer Dim product As Integer = 0 While x >= 1 If x Mod 2 == 1 Then product += y; End If x /= 2 y *= 2 End If Return product End FunctionAdmin
Some considerations for speed optimisation:
unsigned int rmul( unsigned int a, unsigned int b ) { if ( a > b ) rmul( b, a ); unsigned int acc = (a & 1) ? b : 0; for ( ; a >>= 1 ; b <<= 1 ) { if ( a & 1 ) acc += b; } return acc; }Admin
Here's mine, in Python. It works for all integers.
Admin
Mine on javascript function peasentDevide(a, b){r=0;while(a!=0){if (a%2==1)r+=b;a=Math.floor(a/2);b=b*2;}return r;}
Admin
Wrote in D language :P but the mult function should work also in C++, I think...well, with unsigned int instead of uint :P:
import std.stdio; import std.string;
int mult(uint fst, uint snd) { uint result;
}
void main(string[] args) { if(args.length != 3) { writefln("Usage: %s <num> <num>", args[0]); return 0; } if(!args[1].isNumeric()) { writefln("First argument isn't a number"); return 0; } if(!args[2].isNumeric()) { writefln("Second argument isn't a number"); return 0; }
}
To run put it in a file and use the gdc compiler....
Admin
In Python (Works with 0 and negative numbers!)
def p_mult(num1, num2) : if num1 == 0 or num2 == 0 : return 0 sign = bool(num1 < 0) ^ bool(num2 < 0) num1 = abs(num1) num2 = abs(num2) dat = [[num1, num2]] while num1 != 1 : num1 /= 2 num2 *= 2 dat.append([num1, num2]) total = 0 for n in dat : if n[0] % 2 == 1 : total += n[1] if sign : return total * -1 else : return total
http://www.codeskilled.com
Admin
Common Lisp:
(defun russkiply (a b &optional (sum 0)) "returns the product of a and b, achieved by peasant multiplication." (cond ((or (zerop a) (zerop b)) 0) ((minusp a) (- (russkiply (- a) b))) ((minusp b) (- (russkiply a (- b)))) ((= a 1) (+ b sum)) (t (russkiply (floor (/ a 2)) (* b 2) (+ sum (* b (logand a 1)))))))C:
int russkiply (int a, int b) { if (a == 0 || b == 0) { return 0; }; if (a < 0) { return - russkiply (- a, b); }; if (b < 0) { return - russkiply (a, - b); }; int p = 0; for (; p += (a & 1) * b, a != 1; a /= 2, b *= 2) {}; return p; };Admin
My solution in LUA:
Admin
Admin
Windows XP batch file:
@echo off set _a=18 set _b=23 call :mult %_a% %_b% _result echo %_a% x %_b% = %_result% goto :EOF :mult :: Multiply two numbers :: Parameters: :: %1 - first number :: %2 - second number :: %3 - variable to return result in setlocal set _a=%1 set _b=%2 set _res=0 :calc set _eventest=0 for /L %%i in (0,2,8) do if %_a:~-1%==%%i set _eventest=1 if %_eventest%==0 set /a _res+=_b if %_a% LEQ 1 goto endcalc set /a _a/=2 set /a _b*=2 goto calc :endcalc endlocal & set %3=%_res% goto :EOFAdmin
Forgive, i missed the automagic vivification of c to existance and 0
Admin
Python 2.6
51 characters
Admin
Since everyone is bragging about shifting instead of multiply/divide, here is a Pascal version with shifting:
function RussianMultiply(Left, Right: Integer): Integer; begin if (Left = 1) then begin Result := Right; Exit; end; Result := 0; if ((Left mod 2) <> 0) then Inc(Result, Right); while Left <> 1 do begin Left := Left shr 1; Right := Right shl 1; if ((Left mod 2) <> 0) then Inc(Result, Right); end; end;You could strip the
if (Left = 1) then begin Result := Right; Exit; end;part, but it would be slower I guess.
Admin
Shorter: return f>0?m(f>>1,s<<1)+(f&1)*s:0;
Just realized that ( (a&1) == 1? s : 0 ) === ( (a&1)*s )
34 chars without the function header.
Admin
And, for even more fun, with a custom operator
object praxis2 { implicit def RussianIntInt(i: Int):RussianInt = new RussianInt(i) implicit def IntRussianInt(i: RussianInt):Int = i.a class RussianInt(val a: Int) { def ***(b: RussianInt): RussianInt = { if (a < 2) if (a == 1) b else 0 else if (a % 2 == 1) b + ((a / 2) *** (b * 2)) else ((a / 2) *** (b * 2)) } } def main(args: Array[String]) { val a = args(0).toInt val b = args(1).toInt val res: Int = a *** b println(res) } }Admin
Python:
Admin
Final version of my ruby function, slightly altered with some cribbage from halber_mensch to handle all integers.
Admin
Last one I submit, I promise! :)
function RussianMultiply(Left, Right: Integer): Integer; begin Result := 0; if ((Left and 1) = 1) then Inc(Result, Right); while Left <> 1 do begin Left := Left shr 1; Right := Right shl 1; if ((Left and 1) = 1) then Inc(Result, Right); end; end;Admin
Or
X gets a list of powers of two starting with 1
Y gets a list of B times powers of two
Z gets a list of (A/power of two) mod 2 (0 or 1)
RET gets the sum of the list of Y and Z elements multiplied together.
4 lines, no loops, no recursion, and only one Greek letter!
NOT TESTED. Written using a memory of APL not exercised in 25 years.
Admin
Well that one wins Best Abuse Of The Rules.:) I've only seen one C preprocessor nasty so far.... any more takers?
Admin
Here is my MS-Windows Batch file:
Now, how does one get code to single-space?
Admin
A database query syntax error has occurred. This may indicate a bug in the software. The last attempted database query was:
from within function "MediaWikiBagOStuff::_doquery". MySQL returned error "1194: Table 'mw_objectcache' is marked as crashed and should be repaired (localhost)".
Admin
The problem says two numbers, not two integers, so here's the first draft of a PHP solution that will handle decimal fractions (and also negative numbers):
function potemkin_multiply($two_numbers) { $frac_len = array(0, 0); foreach ($two_numbers as $num) { if ($num == 0) { return 0; } $num = rtrim($num, '.'); if ($len = strrchr($num, '.')) { $frac_len[] = strlen(strrchr($num, '.')) - 1; } } $power = max($frac_len); $neg = false; foreach ($two_numbers as & $num) { if ($num < 0) { $neg = !$neg; } $num = abs($num * pow(10, $power)); } $total = 0; while ($two_numbers[0] > 1) { if ($two_numbers[0] % 2) { $total += $two_numbers[1]; } $two_numbers[0] = floor($two_numbers[0] / 2); $two_numbers[1] *= 2; } $total = ($total + $two_numbers[1]) / pow(10, $power * 2); if ($neg) { $total *= -1; } return $total; }Test code:$nums = array(0, -1, 1, 18, -23, 154., -229.5, 49.0, 389.99, 67.99999, -592.8729, .678, 0.00678); for ($i = 0; $i < 50; $i++) { $pair = array($nums[array_rand($nums)], $nums[array_rand($nums)]); $russian = potemkin_multiply($pair); $orthodox = $pair[0] * $pair[1]; echo $pair[0] . ' * ' . $pair[1] . ' = ' . $russian . ''; if ((string) $russian != (string) $orthodox) { echo ' (' . $orthodox . ')'; } echo ''; }
Admin
I know everybody wants it :)
Hopefully none of it was removed.
Also, everything after the first . is disabled debugging code. Remove the [-] to see what is left of the memory.
Admin
48 characters in javascript:
function m(a,b){return a>1?a%2b+m(a>>1,b2):b;}
Admin
Didn't test it, but I think this will infinite loop if the first number is 0;
Admin
Admin
Efficient C solution:
int russianMult( int a, int b ){
}
Admin
All of these solutions are soooooo slooooooooow. Try this one out. Just call the function you need! Ex: for 5 x 18, call "F5x18();". Note: Doesn't yet work for all values, but I'm working on it.
Admin
While I haven't checked if it already exists, here a non-recursive Ruby solution overwriting the default operator.
I couldn't test it, so it'll probably not work.
But it has comments, works with negative numbers, and doesn't interfere with non-integral multiplication.
class Bignum # Save the old multiplication alias old_mult * end class Fixnum # Save the old multiplication alias old_mult * end class Integer def *(b) # Only perform RPM on two integers if b.is_a? Integer # Copy first operand so that it can be modified in place * a = self # If any of the two is 0, result is 0 return 0 if a == 0 or b == 0 # Get the sign of the result ** sgn = ((a <=> 0) + (b <=> 0)).abs - 1 # Get the absolute values a, b = a.abs, b.abs # Initialize the result result = 0 # > 0 because we want to do a last addition when a is 1 while a > 0 # Add b to result if a is odd result += b if a % 2 == 1 a << -1 # Right shift a by one b << 1 # Left shift b by one end # Return the result (also: get the sign right) sgn * result else # Use old multiplication if no Integer supplied old_mult(b) end end end =begin * Not sure if this is neccessary, but as I said, I wasn't able to test it. ** You got it? No? Okay, explanation: a<0^b>0 => (a<=>0)=-1^(b<=>0)=1 => sgn=(-1+1).abs-1=-1 a<0^b<0 => (a<=>0)=-1^(b<=>0)=-1 => sgn(-1-1).abs-1=1 a>0^b>0 => (a<=>0)=1^(b<=>0)=1 => sgn=(1+1).abs-1=1 a>0^b<0 => (a<=>0)=1^(b<=>0)=-1 => sgn(1-1).abs-1=-1 (a<=>0)=0 or (b<=>0)=0 cannot occur, because of the line above that. =endAddendum (2009-07-22 11:36): Okay, so this is one of the least clever solutions... but it is commented like no other. Does this get me a sticker?
Addendum (2009-07-22 13:32): Damn! I'm stupid. Of course, sgn*result is incorrect. Take this instead:
(gotta close those tags.)Admin
switch( x*y ) { case 1: return F1x1(); case 2: return F1x2(); case 3: return F1x3(); case 4: return F2x2(); }As in your code, it won't handle all cases, but you can finish this "enhancement" as you finish your original code.Admin
Exercise for the reader, as always.
Or if you insist:
Admin
Or how about this:
Using multiply and divide expands our domain from N × N to Z × Z. If that's not worth the minor performance penalty, you're doing much more interesting work than I am.Admin
Since I read this as "Multiply exactly like russian peasants would" then I did it the old-fashioned C# way.
public static int RussianPeasantMultiplication(int CurrentLeftValue, int CurrentRightValue) { List<int> LeftColumn = new List<int>(); List<int> RightColumn = new List<int>(); int FinalValue = 0; LeftColumn.Add(CurrentLeftValue); RightColumn.Add(CurrentRightValue); while (true) { CurrentLeftValue = LeftColumn[LeftColumn.Count - 1]; CurrentRightValue = RightColumn[RightColumn.Count - 1]; CurrentLeftValue /= 2; CurrentRightValue *= 2; LeftColumn.Add(CurrentLeftValue); RightColumn.Add(CurrentRightValue); if (CurrentLeftValue <= 1) break; } for (int i = 0; i < LeftColumn.Count; i++) { if (LeftColumn[i] % 2 != 0) FinalValue += RightColumn[i]; } return FinalValue; }Admin
Dammit...Someone beat me the the CF solution...
Where are the COBOL developers? Don't make me bust out my college COBOL!!!
Admin
Zor, this is very useful. Perhaps something like this would make it easier for the user?
#define multiply(X, Y) F##X##x##Y ()
Admin
Did that already...
But...
sub t{$[0]?t($[0]>>1,$[1]<<1)+($[0]&1)*$_[1]:0}
52 char is about as far down as I can get it, and does not handle (-) due to Perl using C shifts, which dont operate properly on (-)..
Admin
inline bool shift(unsigned int& result, unsigned int a, unsigned int b) { return result += a & 1 ? b : 0; }
unsigned int RM(unsigned int a, unsigned int b) { unsigned int result = 0; while (a != 1 && shift(result, a>>=1, b<<=1)) { } return result; }
Admin
public class NotCheating {
}
Admin
Well, what's a promis if you don't break it? :)
function RussianMultiply(Left, Right: Integer): Integer; begin Result := 0; Inc(Result, Right * (Left and 1)); while Left > 1 do begin Left := Left shr 1; Right := Right shl 1; Inc(Result, Right * (Left and 1)); end; end;Admin
C++ version
void russian(int x, int y) { if (x == 0) throw 0; try { russian(x>>1, y<<1); } catch (int a) { throw a + y * (x & 1); } } int multiply(int x, int y) { try { russian(x, y); } catch (int a) { return a; } }