Python Forum
Script optimisation and style help
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Script optimisation and style help
#1
As a long-time Perl coder, I've picked up loads of optimisations and style tips that make scripts easier to understand, shorter, and more efficient.

I occasionally dabble in Python and typically end up brute-forcing some code together using the basic Python capabilities, often thinking how I'd write the script in Perl and then working out the Python equivalent methods. I recently wrote a script to reverse-engineer sample sizes from published percentages, and I suspect it's particularly bad since I directly translated some JavaScript into Python for one of the key functions.

If anyone is able to offer advice on how to improve the script and make it more optimised and Pythonic, I'd be very grateful! I'm working with Python 3.7 simply because it's recent, and not because of any particular attachment to Python 3 over Python 2.

# Determine minimum likely values based on provided percentages

import math

digit_accuracy = 2
results = {}

#percentages = [ 4.71, 20.00, 42.35, 32.94 ]
percentages = [ 8.57, 5.71, 2.86, 20.00, 14.29, 17.14, 20.00, 5.71, 5.71 ]

# Calculate Greatest Common Divisor of two numbers
# Based on code from https://www.programiz.com/python-programming/examples/lcm
def gcd(x, y):
    while(y):
        x, y = y, x % y
    return x

# Calculate Least Common Multiple of two numbers
# Based on code from https://www.programiz.com/python-programming/examples/lcm
def lcm(x, y):
    return ((x * y) // gcd(x, y))

# Use continued fraction method to calculate simplest fraction that represents provided decimal at given precision (decimal places)
# Based on the JavaScript version at http://jonisalonen.com/2012/converting-decimal-numbers-to-ratios/
def estimate_fraction(decimal_value, decimal_precision):
    #print("Estimating fractions for", decimal_value)
    desired_result = round(decimal_value * 100, decimal_precision)
    h1 = 1
    h2 = 0
    k1 = 0
    k2 = 1
    b = decimal_value
    while True:
        a = math.floor(b)
        aux = h1
        h1 = (a * h1) + h2
        h2 = aux
        aux = k1
        k1 = (a * k1) + k2
        k2 = aux

        rounded_result = round(((h1 * 100) / k1), decimal_precision)
        if (rounded_result == desired_result):
            break

        b = 1 / (b - a)

    return [h1, k1]

# ------------------- MAIN -------------------

def main():
    lowest_denominator = 0
    for item in percentages:
        # Find a fraction to estimate the current percentage to the given number of decimal places accuracy
        [numerator, denominator] = estimate_fraction((item / 100), digit_accuracy)
        results[item] = [numerator, denominator]
        # Find the lowest common multiple for the fraction denominators up to this point
        if (lowest_denominator == 0):
            lowest_denominator = denominator
        else:
            lowest_denominator = lcm(denominator, lowest_denominator)

    running_total = 0
    for x in percentages:
        [numerator, denominator] = results[x]
        # Convert all fractions to a common denominator (which should be the sample size)
        if (denominator != lowest_denominator):
            multiplier = lowest_denominator / denominator
            numerator *= multiplier
            denominator *= multiplier
        running_total += numerator

        # Display summary of the calculated values for this entry
        calculated_percentage = round(((numerator * 100) / denominator), digit_accuracy)
        print(int(numerator), " / ", int(denominator), " = ", calculated_percentage, "% (Requested: ", x, "%)", sep="")

    # Print some summary information to help determine if the estimated sample size is sensible
    print("\nTotal", int(running_total), "items represented of", lowest_denominator)
    print("Percentages sum to ", round(sum(percentages), digit_accuracy), "%", sep="")
    

# ---------- ENTRY POINT ----------

if __name__ == '__main__':
    main()
Reply


Messages In This Thread
Script optimisation and style help - by TheFluffyOne - Feb-18-2019, 02:17 PM
RE: Script optimisation and style help - by buran - Feb-18-2019, 04:28 PM
RE: Script optimisation and style help - by buran - Feb-18-2019, 05:52 PM

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020