Karazuba Algorithm with arbitrary basesTiny Encryption Algorithm (TEA) for arbitrary sized dataAlgorithm to...
Diffraction of a wave passing through double slits
POSIX compatible way to get user name associated with a user ID
What is this gigantic dish at Ben Gurion airport?
Is a suit against a University Dorm for changing policies on a whim likely to succeed (USA)?
Why do sellers care about down payments?
Is there any way to land a rover on the Moon without using any thrusters?
What are uses of the byte after BRK instruction on 6502?
What hard drive connector is this?
Why some files are not movable in Windows 10
Real mode flat model
Are space camera sensors usually round, or square?
What does a Light weapon mean mechanically?
How do I say "quirky" in German without sounding derogatory?
What is the derivative of an exponential function with another function as its base?
Can you add polynomial terms to multiple linear regression?
Planar regular languages
How are aircraft depainted?
How do EVA suits manage water excretion?
What officially disallows US presidents from driving?
How to prepare for STEM graduate program while in industry?
Can I fix my boots by gluing the soles back on?
Will the UK home office know about 5 previous visa rejections in other countries?
What is my breathable atmosphere composed of?
How are unbalanced coaxial cables used for broadcasting TV signals without any problems?
Karazuba Algorithm with arbitrary bases
Tiny Encryption Algorithm (TEA) for arbitrary sized dataAlgorithm to get an arbitrary perpendicular vectorChanging algorithm to avoid looping with iterrowsBase converting with strings from bases 1 to 36 to bases 1 to 36Base object to convert positive numbers into other bases (2 <= base <= 35) in Python355 - The Bases Are Loaded (math numbers conversion)(Almost) arbitrary base ints with decorated methodsDijkstra's algorithm with priority queueArbitrary Dice with ProbabilityArbitrary precision Euler-Mascheroni constant via a Brent-McMillan algorithm with no math module
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}
$begingroup$
I'm working on an implementation of the Karazuba Algorithm. I created a class BN
which represents a number in an arbitrary base (and supports elementary operations). The algorithm works - but I'm not sure if I complicated it. Is there a better way to implement it or a way to optimize the code?
def decToBase(n: int, b: int) -> list:
if n == 0:
return [0]
digits = []
while n:
digits.append(int(n % b))
n //= b
return list(reversed(digits))
def baseToDec(n: list, b: int) -> int:
res = 0
for index, i in enumerate(reversed(n)):
res += int(i) * b ** index
return res
from math import log2, ceil, log10, floor
class BN(): # Base Number
def __init__(self, num, base):
if type(num) == list:
self.digits = num
else:
self.digits = decToBase(num, base)
self.base = base
self.length = len(self.digits)
def __add__(self, o):
if self.base != o.base:
raise ValueError("base of summands must be equal")
carry = 0
res = []
for d1, d2 in zip(reversed(self.digits), reversed(o.digits)):
s = int(d1) + int(d2) + carry
res.append(str(s % self.base))
carry = s // self.base
return BN(list(reversed(res)), self.base)
def __mul__(self, o):
# implementation pending
return BN(decToBase(self.getDecimalForm() * o.getDecimalForm(), self.base), self.base)
def __sub__(self, o):
# implementation pending
return BN(decToBase(self.getDecimalForm() - o.getDecimalForm(), self.base), self.base)
def getDecimalForm(self):
return baseToDec(self.digits, self.base)
def karazubaMultiply(a, b, base=2**64):
if a < b:
a, b = b, a # ensure a >= b
next2 = 2 ** ceil(log2(floor(log10(a))+1)) # next power of 2
a, b = BN(a, base), BN(b, base)
a.digits, b.digits = ['0'] * (next2 - a.length) + a.digits, ['0'] * (next2 - b.length) + b.digits
n = next2 // 2
x2, x1 = BN(a.digits[:n], base), BN(a.digits[n:], base)
y2, y1 = BN(b.digits[:n], base), BN(b.digits[n:], base)
p1, p2, p3 = x2 * y2, x1 * y1, (x1 + x2) * (y1 + y2)
p1, p2, p3 = p1.getDecimalForm(), p2.getDecimalForm(), p3.getDecimalForm()
xy = p1 * base ** (2*n) + (p3 - (p1 + p2)) * base ** n + p2
return xy
python performance algorithm number-systems
New contributor
$endgroup$
add a comment
|
$begingroup$
I'm working on an implementation of the Karazuba Algorithm. I created a class BN
which represents a number in an arbitrary base (and supports elementary operations). The algorithm works - but I'm not sure if I complicated it. Is there a better way to implement it or a way to optimize the code?
def decToBase(n: int, b: int) -> list:
if n == 0:
return [0]
digits = []
while n:
digits.append(int(n % b))
n //= b
return list(reversed(digits))
def baseToDec(n: list, b: int) -> int:
res = 0
for index, i in enumerate(reversed(n)):
res += int(i) * b ** index
return res
from math import log2, ceil, log10, floor
class BN(): # Base Number
def __init__(self, num, base):
if type(num) == list:
self.digits = num
else:
self.digits = decToBase(num, base)
self.base = base
self.length = len(self.digits)
def __add__(self, o):
if self.base != o.base:
raise ValueError("base of summands must be equal")
carry = 0
res = []
for d1, d2 in zip(reversed(self.digits), reversed(o.digits)):
s = int(d1) + int(d2) + carry
res.append(str(s % self.base))
carry = s // self.base
return BN(list(reversed(res)), self.base)
def __mul__(self, o):
# implementation pending
return BN(decToBase(self.getDecimalForm() * o.getDecimalForm(), self.base), self.base)
def __sub__(self, o):
# implementation pending
return BN(decToBase(self.getDecimalForm() - o.getDecimalForm(), self.base), self.base)
def getDecimalForm(self):
return baseToDec(self.digits, self.base)
def karazubaMultiply(a, b, base=2**64):
if a < b:
a, b = b, a # ensure a >= b
next2 = 2 ** ceil(log2(floor(log10(a))+1)) # next power of 2
a, b = BN(a, base), BN(b, base)
a.digits, b.digits = ['0'] * (next2 - a.length) + a.digits, ['0'] * (next2 - b.length) + b.digits
n = next2 // 2
x2, x1 = BN(a.digits[:n], base), BN(a.digits[n:], base)
y2, y1 = BN(b.digits[:n], base), BN(b.digits[n:], base)
p1, p2, p3 = x2 * y2, x1 * y1, (x1 + x2) * (y1 + y2)
p1, p2, p3 = p1.getDecimalForm(), p2.getDecimalForm(), p3.getDecimalForm()
xy = p1 * base ** (2*n) + (p3 - (p1 + p2)) * base ** n + p2
return xy
python performance algorithm number-systems
New contributor
$endgroup$
$begingroup$
You're never going to be anywhere near as fast as the builtin integer type. If you want to display as base_x, then you should just build a class that inherits from int, but displays differently, if you care about speed.
$endgroup$
– Gloweye
9 hours ago
$begingroup$
It's clear that it won't be faster than the builtin multiplication. I just want to implement the algorithm - at maximum speed, for learning purpose.
$endgroup$
– Thomas
9 hours ago
add a comment
|
$begingroup$
I'm working on an implementation of the Karazuba Algorithm. I created a class BN
which represents a number in an arbitrary base (and supports elementary operations). The algorithm works - but I'm not sure if I complicated it. Is there a better way to implement it or a way to optimize the code?
def decToBase(n: int, b: int) -> list:
if n == 0:
return [0]
digits = []
while n:
digits.append(int(n % b))
n //= b
return list(reversed(digits))
def baseToDec(n: list, b: int) -> int:
res = 0
for index, i in enumerate(reversed(n)):
res += int(i) * b ** index
return res
from math import log2, ceil, log10, floor
class BN(): # Base Number
def __init__(self, num, base):
if type(num) == list:
self.digits = num
else:
self.digits = decToBase(num, base)
self.base = base
self.length = len(self.digits)
def __add__(self, o):
if self.base != o.base:
raise ValueError("base of summands must be equal")
carry = 0
res = []
for d1, d2 in zip(reversed(self.digits), reversed(o.digits)):
s = int(d1) + int(d2) + carry
res.append(str(s % self.base))
carry = s // self.base
return BN(list(reversed(res)), self.base)
def __mul__(self, o):
# implementation pending
return BN(decToBase(self.getDecimalForm() * o.getDecimalForm(), self.base), self.base)
def __sub__(self, o):
# implementation pending
return BN(decToBase(self.getDecimalForm() - o.getDecimalForm(), self.base), self.base)
def getDecimalForm(self):
return baseToDec(self.digits, self.base)
def karazubaMultiply(a, b, base=2**64):
if a < b:
a, b = b, a # ensure a >= b
next2 = 2 ** ceil(log2(floor(log10(a))+1)) # next power of 2
a, b = BN(a, base), BN(b, base)
a.digits, b.digits = ['0'] * (next2 - a.length) + a.digits, ['0'] * (next2 - b.length) + b.digits
n = next2 // 2
x2, x1 = BN(a.digits[:n], base), BN(a.digits[n:], base)
y2, y1 = BN(b.digits[:n], base), BN(b.digits[n:], base)
p1, p2, p3 = x2 * y2, x1 * y1, (x1 + x2) * (y1 + y2)
p1, p2, p3 = p1.getDecimalForm(), p2.getDecimalForm(), p3.getDecimalForm()
xy = p1 * base ** (2*n) + (p3 - (p1 + p2)) * base ** n + p2
return xy
python performance algorithm number-systems
New contributor
$endgroup$
I'm working on an implementation of the Karazuba Algorithm. I created a class BN
which represents a number in an arbitrary base (and supports elementary operations). The algorithm works - but I'm not sure if I complicated it. Is there a better way to implement it or a way to optimize the code?
def decToBase(n: int, b: int) -> list:
if n == 0:
return [0]
digits = []
while n:
digits.append(int(n % b))
n //= b
return list(reversed(digits))
def baseToDec(n: list, b: int) -> int:
res = 0
for index, i in enumerate(reversed(n)):
res += int(i) * b ** index
return res
from math import log2, ceil, log10, floor
class BN(): # Base Number
def __init__(self, num, base):
if type(num) == list:
self.digits = num
else:
self.digits = decToBase(num, base)
self.base = base
self.length = len(self.digits)
def __add__(self, o):
if self.base != o.base:
raise ValueError("base of summands must be equal")
carry = 0
res = []
for d1, d2 in zip(reversed(self.digits), reversed(o.digits)):
s = int(d1) + int(d2) + carry
res.append(str(s % self.base))
carry = s // self.base
return BN(list(reversed(res)), self.base)
def __mul__(self, o):
# implementation pending
return BN(decToBase(self.getDecimalForm() * o.getDecimalForm(), self.base), self.base)
def __sub__(self, o):
# implementation pending
return BN(decToBase(self.getDecimalForm() - o.getDecimalForm(), self.base), self.base)
def getDecimalForm(self):
return baseToDec(self.digits, self.base)
def karazubaMultiply(a, b, base=2**64):
if a < b:
a, b = b, a # ensure a >= b
next2 = 2 ** ceil(log2(floor(log10(a))+1)) # next power of 2
a, b = BN(a, base), BN(b, base)
a.digits, b.digits = ['0'] * (next2 - a.length) + a.digits, ['0'] * (next2 - b.length) + b.digits
n = next2 // 2
x2, x1 = BN(a.digits[:n], base), BN(a.digits[n:], base)
y2, y1 = BN(b.digits[:n], base), BN(b.digits[n:], base)
p1, p2, p3 = x2 * y2, x1 * y1, (x1 + x2) * (y1 + y2)
p1, p2, p3 = p1.getDecimalForm(), p2.getDecimalForm(), p3.getDecimalForm()
xy = p1 * base ** (2*n) + (p3 - (p1 + p2)) * base ** n + p2
return xy
python performance algorithm number-systems
python performance algorithm number-systems
New contributor
New contributor
edited 9 hours ago
200_success
136k21 gold badges175 silver badges445 bronze badges
136k21 gold badges175 silver badges445 bronze badges
New contributor
asked 9 hours ago
ThomasThomas
411 bronze badge
411 bronze badge
New contributor
New contributor
$begingroup$
You're never going to be anywhere near as fast as the builtin integer type. If you want to display as base_x, then you should just build a class that inherits from int, but displays differently, if you care about speed.
$endgroup$
– Gloweye
9 hours ago
$begingroup$
It's clear that it won't be faster than the builtin multiplication. I just want to implement the algorithm - at maximum speed, for learning purpose.
$endgroup$
– Thomas
9 hours ago
add a comment
|
$begingroup$
You're never going to be anywhere near as fast as the builtin integer type. If you want to display as base_x, then you should just build a class that inherits from int, but displays differently, if you care about speed.
$endgroup$
– Gloweye
9 hours ago
$begingroup$
It's clear that it won't be faster than the builtin multiplication. I just want to implement the algorithm - at maximum speed, for learning purpose.
$endgroup$
– Thomas
9 hours ago
$begingroup$
You're never going to be anywhere near as fast as the builtin integer type. If you want to display as base_x, then you should just build a class that inherits from int, but displays differently, if you care about speed.
$endgroup$
– Gloweye
9 hours ago
$begingroup$
You're never going to be anywhere near as fast as the builtin integer type. If you want to display as base_x, then you should just build a class that inherits from int, but displays differently, if you care about speed.
$endgroup$
– Gloweye
9 hours ago
$begingroup$
It's clear that it won't be faster than the builtin multiplication. I just want to implement the algorithm - at maximum speed, for learning purpose.
$endgroup$
– Thomas
9 hours ago
$begingroup$
It's clear that it won't be faster than the builtin multiplication. I just want to implement the algorithm - at maximum speed, for learning purpose.
$endgroup$
– Thomas
9 hours ago
add a comment
|
1 Answer
1
active
oldest
votes
$begingroup$
Combine division and modulus
Use https://docs.python.org/3/library/functions.html#divmod
rather than this:
digits.append(int(n % b))
n //= b
Replace loop with sum
This
res = 0
for index, i in enumerate(reversed(n)):
res += int(i) * b ** index
return res
is a good candidate for conversion to a generator, i.e.
return sum(int(i) * b**index for index, i in enumerate(reversed(n)))
However, you can get rid of that reversed
if you change the power index
to be len(n) - index
.
Imports at the top
Move this:
from math import log2, ceil, log10, floor
to the top of your file.
Don't compare types
Rather than this:
if type(num) == list:
use isinstance
.
Member mutability
You shouldn't care that num
is coming in as a list; you should only check that it's iterable. And store it as a tuple, not a list, because you don't (and shouldn't) mutate it in your class code.
Call reversed
once
This:
zip(reversed(self.digits), reversed(o.digits))
should be
reversed(zip(self.digits, o.digits))
Don't use strings for math
Just don't. This:
a.digits, b.digits = ['0']
is not a good idea. Use actual digits whenever possible, and it is possible here.
$endgroup$
add a comment
|
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Thomas is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f228924%2fkarazuba-algorithm-with-arbitrary-bases%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
Combine division and modulus
Use https://docs.python.org/3/library/functions.html#divmod
rather than this:
digits.append(int(n % b))
n //= b
Replace loop with sum
This
res = 0
for index, i in enumerate(reversed(n)):
res += int(i) * b ** index
return res
is a good candidate for conversion to a generator, i.e.
return sum(int(i) * b**index for index, i in enumerate(reversed(n)))
However, you can get rid of that reversed
if you change the power index
to be len(n) - index
.
Imports at the top
Move this:
from math import log2, ceil, log10, floor
to the top of your file.
Don't compare types
Rather than this:
if type(num) == list:
use isinstance
.
Member mutability
You shouldn't care that num
is coming in as a list; you should only check that it's iterable. And store it as a tuple, not a list, because you don't (and shouldn't) mutate it in your class code.
Call reversed
once
This:
zip(reversed(self.digits), reversed(o.digits))
should be
reversed(zip(self.digits, o.digits))
Don't use strings for math
Just don't. This:
a.digits, b.digits = ['0']
is not a good idea. Use actual digits whenever possible, and it is possible here.
$endgroup$
add a comment
|
$begingroup$
Combine division and modulus
Use https://docs.python.org/3/library/functions.html#divmod
rather than this:
digits.append(int(n % b))
n //= b
Replace loop with sum
This
res = 0
for index, i in enumerate(reversed(n)):
res += int(i) * b ** index
return res
is a good candidate for conversion to a generator, i.e.
return sum(int(i) * b**index for index, i in enumerate(reversed(n)))
However, you can get rid of that reversed
if you change the power index
to be len(n) - index
.
Imports at the top
Move this:
from math import log2, ceil, log10, floor
to the top of your file.
Don't compare types
Rather than this:
if type(num) == list:
use isinstance
.
Member mutability
You shouldn't care that num
is coming in as a list; you should only check that it's iterable. And store it as a tuple, not a list, because you don't (and shouldn't) mutate it in your class code.
Call reversed
once
This:
zip(reversed(self.digits), reversed(o.digits))
should be
reversed(zip(self.digits, o.digits))
Don't use strings for math
Just don't. This:
a.digits, b.digits = ['0']
is not a good idea. Use actual digits whenever possible, and it is possible here.
$endgroup$
add a comment
|
$begingroup$
Combine division and modulus
Use https://docs.python.org/3/library/functions.html#divmod
rather than this:
digits.append(int(n % b))
n //= b
Replace loop with sum
This
res = 0
for index, i in enumerate(reversed(n)):
res += int(i) * b ** index
return res
is a good candidate for conversion to a generator, i.e.
return sum(int(i) * b**index for index, i in enumerate(reversed(n)))
However, you can get rid of that reversed
if you change the power index
to be len(n) - index
.
Imports at the top
Move this:
from math import log2, ceil, log10, floor
to the top of your file.
Don't compare types
Rather than this:
if type(num) == list:
use isinstance
.
Member mutability
You shouldn't care that num
is coming in as a list; you should only check that it's iterable. And store it as a tuple, not a list, because you don't (and shouldn't) mutate it in your class code.
Call reversed
once
This:
zip(reversed(self.digits), reversed(o.digits))
should be
reversed(zip(self.digits, o.digits))
Don't use strings for math
Just don't. This:
a.digits, b.digits = ['0']
is not a good idea. Use actual digits whenever possible, and it is possible here.
$endgroup$
Combine division and modulus
Use https://docs.python.org/3/library/functions.html#divmod
rather than this:
digits.append(int(n % b))
n //= b
Replace loop with sum
This
res = 0
for index, i in enumerate(reversed(n)):
res += int(i) * b ** index
return res
is a good candidate for conversion to a generator, i.e.
return sum(int(i) * b**index for index, i in enumerate(reversed(n)))
However, you can get rid of that reversed
if you change the power index
to be len(n) - index
.
Imports at the top
Move this:
from math import log2, ceil, log10, floor
to the top of your file.
Don't compare types
Rather than this:
if type(num) == list:
use isinstance
.
Member mutability
You shouldn't care that num
is coming in as a list; you should only check that it's iterable. And store it as a tuple, not a list, because you don't (and shouldn't) mutate it in your class code.
Call reversed
once
This:
zip(reversed(self.digits), reversed(o.digits))
should be
reversed(zip(self.digits, o.digits))
Don't use strings for math
Just don't. This:
a.digits, b.digits = ['0']
is not a good idea. Use actual digits whenever possible, and it is possible here.
answered 9 hours ago
ReinderienReinderien
8,37013 silver badges38 bronze badges
8,37013 silver badges38 bronze badges
add a comment
|
add a comment
|
Thomas is a new contributor. Be nice, and check out our Code of Conduct.
Thomas is a new contributor. Be nice, and check out our Code of Conduct.
Thomas is a new contributor. Be nice, and check out our Code of Conduct.
Thomas is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f228924%2fkarazuba-algorithm-with-arbitrary-bases%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
$begingroup$
You're never going to be anywhere near as fast as the builtin integer type. If you want to display as base_x, then you should just build a class that inherits from int, but displays differently, if you care about speed.
$endgroup$
– Gloweye
9 hours ago
$begingroup$
It's clear that it won't be faster than the builtin multiplication. I just want to implement the algorithm - at maximum speed, for learning purpose.
$endgroup$
– Thomas
9 hours ago