In python, how to generate a random number such that it is not a power of 2? The output needs to be a list of 8 random numbers. This should be done in a single statement (comprehension style) in python.
Asked
Active
Viewed 167 times
0
-
2What part are you having troubles with? – Guy Jan 22 '20 at 06:36
-
Generate a random number. If the last digit is 2, 4, 6, 8, add 1. No power of 2 can end in 0 or an odd digit. – rossum Jan 22 '20 at 09:27
-
Random from what overall pool? With or without repetitions? – user2390182 Jan 22 '20 at 10:31
-
Thanks, quite helpful – Rohan Jan 29 '20 at 19:16
2 Answers
0
Try the code below,
def is_power_of_two (x):
return (x and (not(x & (x - 1))) )
def get_random(start, stop):
while True:
value = random.randint(start, stop)
if not is_power_of_two(value):
return value
return [i for i in range(limit) if not is_power_of_two(i)]
result = [get_random(0, 10000000000) for _ in range(8)]

Shibiraj
- 769
- 4
- 9
-
This will work fine for small values of `limit`, but will probably crash and burn if `limit` is a billion or more. – r3mainer Jan 22 '20 at 10:25
0
This is the sort of situation where a generator would come in useful. Write a function with an infinite loop that returns random numbers that meet your criteria, then use a yield
statement to return these values one at a time whenever the function is called.
Here's an example. I've added a bit of code to check the input parameters to make sure there are valid results in the given range.
def random_not_power_of_2(rmin, rmax):
# Returns a random number r such that rmin <= r < rmax,
# and r is not a power of 2
from random import randint
# Sanity check
if rmin < 0:
raise ValueError("rmin must be non-negative")
if rmax <= rmin:
raise ValueError("rmax must be greater than rmin")
# Abort if the given range contains no valid numbers
r = rmin
isValid = False
while r < rmax:
if r == 0 or (r & (r-1) > 0):
isValid = True
break
r += 1
if not isValid:
raise ValueError("no valid numbers in this range")
while True:
r = randint(rmin, rmax)
if r == 0 or (r & (r-1) > 0):
yield r
def get_random_list(rmin, rmax, n):
# Returns a list of n random numbers in the given range
gen = random_not_power_of_2(rmin, rmax)
return [next(gen) for i in range(n)]
get_random_list(0,17,10)

r3mainer
- 23,981
- 3
- 51
- 88