Python Forum
Calculate the multiple of a number - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: Homework (https://python-forum.io/forum-9.html)
+--- Thread: Calculate the multiple of a number (/thread-25258.html)



Calculate the multiple of a number - pythonuser1 - Mar-24-2020

Hello,

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Les nombre multiples de n compris entre 1 et 60
def multiple(n):
    for i in range(1,61):
        r=i//n
        if i%n==0:
            print(i,r)
    return(r)
print(multiple(15))
The output of the script is like this :
./multiple_nombre_v3.py
(15, 1)
(30, 2)
(45, 3)
(60, 4)
4

My script is giving the multiple of a number (here 15 for example) and the script is working.
I want to optimize it. I have these two lines print(i,r) and return(r ). Is there a way I can get rid of one of these two lines and yet have the correct output giving only the multiple of a number ? I am asking this because the return(r ) sends "4" and in the 'if condition' I did not find an another way besides "print(i,r)" to show the multiples of a number.


RE: Calculate the multiple of a number - deanhystad - Mar-25-2020

The test for multiples is odd. Multiples of 15 will be 15, 30, 45, 60, …. There is no reason for me to test 1, 2, ...14, 15 etc. Reversing your logic to generate multiples and stop when the multiple is out of range would be a lot more efficient.

But that is not what you are asking. I'm not exactly sure what you are asking. Do you want the multiples printed out or not? Or do you want to return the multiples, say in a list, instead of printing them out? Do you want the program to return [15, 30, 45, 60] instead of 4?


RE: Calculate the multiple of a number - ndc85430 - Mar-25-2020

In general, it's better to make the function just return the values, not printing as well. Having the printing in there is extra coupling you don't need - it makes the function less reusable and harder to test.


RE: Calculate the multiple of a number - Fre3k - Mar-25-2020

(Mar-24-2020, 10:30 PM)pythonuser1 Wrote:

Just save the data in a dict, and return the dict.
( didnt change the logic how you get to the result, just added the dict )
def multiple(n):
    retDict={}
    for i in range(1,61):
        r=i//n
        if i%n==0:
            retDict.update({i:r})
            #print({i,r})
    return(retDict)

print(multiple(50))
Output:
{50: 1}
with
multiple(15)
you would get
Output:
{15: 1, 30: 2, 45: 3, 60: 4}
You can change the output as you like. I just printed the dict


RE: Calculate the multiple of a number - DeaD_EyE - Mar-25-2020

(Mar-24-2020, 10:30 PM)pythonuser1 Wrote: I want to optimize it. I have these two lines print(i,r) and return(r ). Is there a way I can get rid of one of these two lines and yet have the correct output giving only the multiple of a number ? I am asking this because the return(r ) sends "4" and in the 'if condition' I did not find an another way besides "print(i,r)" to show the multiples of a number.
  • You should use Python 3. Currently you're using Python 2.7, which is outdated since January 2020.
  • Encoding comment is not needed for Python 3. All source files are encoded with utf8
  • Instead of comments, you can use docstrings
  • You should change the shebang to #!/usr/bin/env python3
  • Your function has side effects. Side effect means, that your function modifies the environment (print to stdout) and return a value. A Pure function takes arguments, does the work and return the result. Nothing else happens beside. Easy fix: remove the print from this function
  • Use better names for objects. n, i, r are bad names.
  • Give the user the flexibility to call your function with different range for start and end.
  • To get rid of return, you could use a generator.


#!/usr/bin/env python3


# value is a positional argument
# start and stop are keyword-only-arguments, the * does this
def multiple_of(value, *, start, stop):
    """
    Les nombre multiples de value compris entre start et stop

    start is inclusive
    stop is inclusive
    """
    for factor in range(start, stop + 1):
        if factor % value == 0:
            yield factor, factor // value  # <- this are the values for each step
                                           #    which goes to the consumer


multi_gen = multiple_of(15, start=1, stop=60)
# multi_gen is a generator, lazy evaluation, no values yet
my_results = list(multi_gen) # list consumes the generator
print(my_results)
# a generator can be consumed only once and then it's exhausted
# if you need the elements in a different datatype as a list:

# multi_gen = multiple_of(15, start=1, stop=60)
# my_results = tuple(multi_gen)

# You can also iterate over the generator:
for result in multiple_of(15, start=1, stop=60):
    print(result)


# Bonus
# You can create also a dict from the results.
# my_results_as_dict = dict(multiple_of(15, start=1, stop=60))



RE: Calculate the multiple of a number - deanhystad - Mar-25-2020

A generator is the best solution as it works for any range without making huge data structures. Plus you can always use a generator to make a list. A dictionary would be silly.

The test for multiples is still goofy. The biggest optimization improvements come from algorithm. What if someone wanted multiples of a billion? The code below completes in a fraction of a second. Using the modulo test I gave up waiting after 5 minutes.
import math

def multiple_of(value, *, start=1, stop=60):
    start = math.ceil(start / value) * value
    while start <= stop:
        yield start, start // value
        start += value

multiples = [v for v, m in multiple_of(1000000000, stop=100000000000)]
print(len(multiples))
Output:
100
If all you want is the count, further optimizations are possible that eliminate looping.


RE: Calculate the multiple of a number - ibreeden - Mar-27-2020

(Mar-24-2020, 10:30 PM)pythonuser1 Wrote: I want to optimize it. I have these two lines print(i,r) and return(r ). Is there a way I can get rid of one of these two lines and yet have the correct output giving only the multiple of a number ?
# -*- coding: utf-8 -*-
# Les nombre multiples de n compris entre 1 et 60
def multiple(n):
    return int(60/n)

print(multiple(15))
Output:
4



RE: Calculate the multiple of a number - deanhystad - Mar-27-2020

Not a useful function anymore, but it could be made a generic solution for any range and any multiple.