Long multiplication: Difference between revisions
(added python) |
(added Haskell) |
||
Line 5: | Line 5: | ||
The output of 2^64 * 2^64 is 2^128, and that is: |
The output of 2^64 * 2^64 is 2^128, and that is: |
||
340282366920938463463374607431768211456 |
340282366920938463463374607431768211456 |
||
=={{header|Haskell}}== |
|||
<lang haskell>digits :: Integer -> [Integer] |
|||
digits = map (fromIntegral.digitToInt) . show |
|||
lZZ = inits $ repeat 0 |
|||
table f = map . flip (map . f) |
|||
polymul = ((map sum . transpose . zipWith (++) lZZ) .) . table (*) |
|||
longmult = (foldl1 ((+) . (10 *)) .) . (. digits) . polymul . digits</lang> |
|||
Output: |
|||
<lang haskell>*Main> (2^64) `longmult` (2^64) |
|||
340282366920938463463374607431768211456</lang> |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |
Revision as of 13:27, 25 February 2009
You are encouraged to solve this task according to the task description, using any language you may know.
In this task, explicitly implement long multiplication. This is one possible approach to arbitrary-precision integer algebra.
For output, display the result of 2^64 * 2^64. The decimal representation of 2^64 is:
18446744073709551616
The output of 2^64 * 2^64 is 2^128, and that is:
340282366920938463463374607431768211456
Haskell
<lang haskell>digits :: Integer -> [Integer] digits = map (fromIntegral.digitToInt) . show
lZZ = inits $ repeat 0
table f = map . flip (map . f)
polymul = ((map sum . transpose . zipWith (++) lZZ) .) . table (*)
longmult = (foldl1 ((+) . (10 *)) .) . (. digits) . polymul . digits</lang> Output: <lang haskell>*Main> (2^64) `longmult` (2^64) 340282366920938463463374607431768211456</lang>
Perl
<lang perl>#!/usr/bin/perl -w use strict;
- This should probably be done in a loop rather than be recursive.
sub add_with_carry {
my $resultref = shift; my $addend = shift; my $addendpos = shift;
push @$resultref, (0) while (scalar @$resultref < $addendpos + 1); my $addend_result = $addend + $resultref->[$addendpos]; my @addend_digits = reverse split //, $addend_result; $resultref->[$addendpos] = shift @addend_digits;
my $carry_digit = shift @addend_digits; &add_with_carry($resultref, $carry_digit, $addendpos + 1) if( defined $carry_digit )
}
sub longhand_multiplication {
my @multiplicand = reverse split //, shift; my @multiplier = reverse split //, shift; my @result = (); my $multiplicand_offset = 0; foreach my $multiplicand_digit (@multiplicand) { my $multiplier_offset = $multiplicand_offset; foreach my $multiplier_digit (@multiplier) { my $multiplication_result = $multiplicand_digit * $multiplier_digit; my @result_digit_addend_list = reverse split //, $multiplication_result;
my $addend_offset = $multiplier_offset; foreach my $result_digit_addend (@result_digit_addend_list) { &add_with_carry(\@result, $result_digit_addend, $addend_offset++) }
++$multiplier_offset; }
++$multiplicand_offset; }
@result = reverse @result;
return join , @result;
}
my $sixtyfour = "18446744073709551616";
my $onetwentyeight = &longhand_multiplication($sixtyfour, $sixtyfour); print "$onetwentyeight\n";</lang>
Python
<lang python>#!/usr/bin/env python
def add_with_carry(result, addend, addendpos):
while True: while len(result) < addendpos + 1: result.append(0) addend_result = str(int(addend) + int(result[addendpos])) addend_digits = list(addend_result) result[addendpos] = addend_digits.pop()
if not addend_digits: break addend = addend_digits.pop() addendpos += 1
def longhand_multiplication(multiplicand, multiplier):
result = [] for multiplicand_offset, multiplicand_digit in enumerate(reversed(multiplicand)): for multiplier_offset, multiplier_digit in enumerate(reversed(multiplier), start=multiplicand_offset): multiplication_result = str(int(multiplicand_digit) * int(multiplier_digit))
for addend_offset, result_digit_addend in enumerate(reversed(multiplication_result), start=multiplier_offset): add_with_carry(result, result_digit_addend, addend_offset)
result.reverse()
return .join(result)
if __name__ == "__main__":
sixtyfour = "18446744073709551616"
onetwentyeight = longhand_multiplication(sixtyfour, sixtyfour) print(onetwentyeight)</lang>