Thursday, July 21, 2022

[FIXED] How to get the gratest common divisor as integer in python from a list of floats?

Issue

I have a list of floats

l1 = [10.0, 50.0, 100.0]
l2 = [0.1, 0.5, 1.0]
l3 = [20.0, 100.0, 200.0]

All should return:

i = [1, 5, 10]

What's the most effective way of getting ints with taking the smaller as the base there multiplier? or a multiples of them if it's not possible

Example:

n1 = [0.2, 0.3, 0.6]

should return

i = [2, 3, 6]

and

 n2 = [1424.56, 2136.84, 4985.96]

should return:

 i = [ 2, 3, 7] # 712.28 = 1

I'm using the value / min(l1) but it wont work for the second case and third case


Solution

You could convert all of the numbers to integers, then divide each by their greatest common divisor (GCD). It's a good idea to avoid floating point numbers due to their inability to represent many decimals exactly. The fractions module is perfect for this: it can handle both decimals and rational numbers like 1/3 and 2/7.

#!/usr/bin/env python3

from fractions import Fraction
from functools import reduce
from math import gcd

def lcm(a, b):
    return a * b // gcd(a, b)

def common_integer(*numbers):
    fractions = [Fraction(n).limit_denominator() for n in numbers]
    multiple  = reduce(lcm, [f.denominator for f in fractions])
    ints      = [int(f * multiple) for f in fractions]
    divisor   = reduce(gcd, ints)
    return [int(n / divisor) for n in ints]

This converts each number to a rational fraction, then multiplies them by the least common multiple (LCM) of their denominators. That effectively scales them up so they're all integers. Then it divides them by their collective GCD, scaling them down as much as possible.

Example:

>>> common_integer('0.2', '0.3', '0.6')
[2, 3, 6]
>>> common_integer('1424.56', '2136.84', '4985.96')
[2, 3, 7]
>>> common_integer('2/7', '18/42', '1/3')
[6, 9, 7]

(Using limit_denominator() allows floats to be passed in, even inexact ones. It's not entirely recommended, but you could omit the quotes and pass 0.2 in place of '0.2' or 1/3 in place of '1/3'.)



Answered By - John Kugelman
Answer Checked By - Terry (PHPFixing Volunteer)

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.