Home > Enterprise >  How to multiply a number until it reaches a specific number in Python?
How to multiply a number until it reaches a specific number in Python?

Time:02-12

I want this code to multiply this list until all numbers exceeds 100, but I am struggling in the loop part.

import numpy as np

a = np.array([230, 10, 284, 39, 76])

def all_30_or_up(ls):
    for i in ls:
        if i < 100:
            return False
    return True

while True:
    if all_30_or_up(a) == False:
        print(a*2)
    else:
        break

This exercise is from the book "How to Think Like a Computer Scientist: Learning with Python 3". That's the actual question in the book:

"Use a mask to multiply all values below 100 in the following list by 2:

a = np.array([230, 10, 284, 39, 76])

Repeat this until all values are above 100. (Not manually, but by looping) Then, select all values between 150 < a < 200."

CodePudding user response:

As the question states, you need to use a mask here to select the indices where the value is below 100. Let's use the dataset given by the exercise.

import numpy as np
a = np.array([230, 10, 284, 39, 76])

First we need to be able to efficiently check if all values are above 100 or not. We can do so by performing comparison over the whole array, which returns an array of boolean, and check their values:

# To check if all values are above 100:
np.all(a>100) # or alternatively: np.any(a<100)

Now we need a way to select only indices where the value is below 100. Fortunately, we can use complex indexing with numpy, and actually use a comparison over the whole array, which gives an array of boolean, and use it inside the [] to select indices where the result of the comparison is True. We then multiply those by two, and update them.

a[a<100] = a[a<100]*2
# or inplace multiplication:
a[a<100] *= 2

Now we need to put all that into a loop:

while not np.all(a>100):
    a[a<100] *= 2

And here you have it!

CodePudding user response:

Numpy allows for conditional selection and multiplication:

import numpy as np

a = np.array([230, 10, 284, 39, 76])

while a [a<100].any():   # loop and check if any < 100
        a [a<100] *= 2   # using a mask to multiply
        print(a)

print("done")

Output:

[230  20 284  78 152]
[230  40 284 156 152]
[230  80 284 156 152]
[230 160 284 156 152]
done

Use print(a[(a>150) * (a<200)]) to filter down to [160 156 152]

CodePudding user response:

You start off with a = np.array([230, 10, 284, 39, 76])

Now, you want to continue looping while any of the values in a are less than 100. Since a is a numpy array, the best way to do this is to check which values are less than 100, and then run the np.any() function.

while (a < 100).any():
    # do something

Now, we want to multiply the values that are less than 100 by 2. Remember, we want to modify the original array.

where_to_multiply = a < 100 # Gives an array of True / False.
a[where_to_multiply] = a[where_to_multiply] * 2

All combined, and if your python version supports the walrus operator, you can do:

while ((where_to_multiply := a < 100)).any():
    a[where_to_multiply] = a[where_to_multiply] * 2
    print(a)

Which gives the output:

[230  20 284  78 152]
[230  40 284 156 152]
[230  80 284 156 152]
[230 160 284 156 152]

Finally, you can filter out the unwanted values using a similar logical indexing:

gt_150 = a > 150
lt_200 = a < 200
select_elem = np.logical_and(gt_150, lt_200)
filtered_a = a[select_elem] # array([160, 156, 152])

CodePudding user response:

You can get the final values in one step by computing the power of 2 that needs to be multiplied with each item to reach 100 (which is the very definition of a logarithm):

import numpy as np

a = np.array([230, 10, 284, 39, 76])
        
p2 = np.maximum(0,np.ceil(np.log2(100/a))).astype(np.int)

a *= 2**p2           # [230 160 284 156 152]

a[(150<a)&(a<200)]   # [160 156 152]

If you need it to be a loop, you can determine the number of iterations ahead of time by applying the same technique to the smallest number in the array:

p2 = max(0,np.ceil(np.log2(100/np.min(a))).astype(np.int))

for _ in range(p2):
    a[a<100] *= 2
  • Related