patternpythonModerate
Rounding a number up to the nearest multiple of a power of 2
Viewed 0 times
numberthenearestpowermultiplerounding
Problem
I'm doing some programming challenges over at
Given numbers x and n, where n is a power of 2, print out the smallest multiple of n which is greater than or equal to x. Do not use division or modulo operator.
So the input looks something like this:
My question is, is it considered bad form to use
CodeEval and came across a pretty straight forward simple one:Given numbers x and n, where n is a power of 2, print out the smallest multiple of n which is greater than or equal to x. Do not use division or modulo operator.
So the input looks something like this:
13, 8 first number being x second number being n. My first instinct was to use a while loop and return the result of multiplying the number once the loop hits the correct result, so:8 * 0 = 0
8 * 1 = 8
8 * 2 = 16; break because it's greater then 13My question is, is it considered bad form to use
float("inf") instead of a set number to multiply up to?import sys
def multiply(x, y):
max_multiple_try = 0
while max_multiple_try != float("inf"):
res = x * max_multiple_try
if res != x and res >= y:
return res
else:
max_multiple_try += 1
if __name__ == '__main__':
with open(sys.argv[1]) as data:
for line in data.readlines():
numbers = line.rstrip().split(",")
print(multiply(int(numbers[1]), int(numbers[0])))Solution
Function interface
First of all, it is good that you used a function to contain the code solving the problem!
However, there are some shortcomings:
-
It is very confusing that the function parameter representing \$n\$ from the problem description is named
-
The function is badly named, as it doesn't multiply the two arguments. A better name would be
-
The function lacks a docstring which describes what it does. It is therefore hard to check if it is implemented correctly. The first sentence of the problem description would make a good docstring (replacing "print out" with "return").
Bug
The function returns the wrong result if both arguments are the same, for example:
But the smallest multiple of 8 which is greater than or equal to 8 should be 8, not 16.
(Maybe you thought that 8 is not considered a multiple of 8?)
The bug is fixed by removing the
Loop exit condition
Let's ignore everything that doesn't affect the
We can see that it is always an integer (which has unlimited size in Python). Therefore it can never be equal to the special
However, as
Top-level code
Congratulations on using
Here are some improvements:
-
Iterate directly over
-
Use tuple assignment:
Alternative algorithm
The problem states that the value of \$n\$ is constrained to powers of two. While your solution actually solves the more general problem for any value of \$n\$, this description probably aims for a different algorithm which makes use of the constraint.
Hint: What does the binary representation of powers of two look like? How could you solve the problem if \$n\$ were constrained to powers of ten?
First of all, it is good that you used a function to contain the code solving the problem!
However, there are some shortcomings:
-
It is very confusing that the function parameter representing \$n\$ from the problem description is named
x, and the one representing \$x\$ is named y. -
The function is badly named, as it doesn't multiply the two arguments. A better name would be
smallest_multiple or similar.-
The function lacks a docstring which describes what it does. It is therefore hard to check if it is implemented correctly. The first sentence of the problem description would make a good docstring (replacing "print out" with "return").
Bug
The function returns the wrong result if both arguments are the same, for example:
>>> multiply(8, 8)
16But the smallest multiple of 8 which is greater than or equal to 8 should be 8, not 16.
(Maybe you thought that 8 is not considered a multiple of 8?)
The bug is fixed by removing the
res != x condition.Loop exit condition
Let's ignore everything that doesn't affect the
max_multiple_try variable:max_multiple_try = 0
while max_multiple_try != float("inf"):
…
if …:
…
else:
max_multiple_try += 1We can see that it is always an integer (which has unlimited size in Python). Therefore it can never be equal to the special
float('inf') value, and the loop could as well have been written using while True: ….However, as
max_multiple_try simply counts the loop iterations, this pattern would be better written as a for loop using itertools.count (and using a simpler and more descriptive name):from itertools import count
…
for factor in count(): # factor = 0, 1, 2, …
res = x * factor
if res >= y:
return resTop-level code
Congratulations on using
if __name__ == '__main__' and using with to open a file!Here are some improvements:
-
Iterate directly over
data instead of using readlines.-
Use tuple assignment:
x, n = line.rstrip().split(",")
print(multiply(int(n), int(x)))Alternative algorithm
The problem states that the value of \$n\$ is constrained to powers of two. While your solution actually solves the more general problem for any value of \$n\$, this description probably aims for a different algorithm which makes use of the constraint.
Hint: What does the binary representation of powers of two look like? How could you solve the problem if \$n\$ were constrained to powers of ten?
Code Snippets
>>> multiply(8, 8)
16max_multiple_try = 0
while max_multiple_try != float("inf"):
…
if …:
…
else:
max_multiple_try += 1from itertools import count
…
for factor in count(): # factor = 0, 1, 2, …
res = x * factor
if res >= y:
return resx, n = line.rstrip().split(",")
print(multiply(int(n), int(x)))Context
StackExchange Code Review Q#147315, answer score: 10
Revisions (0)
No revisions yet.