Dado un conjunto de enteros (por ejemplo, {1000000, 20000000, 1234000, 1200000}
), quiero aplicar a todos ellos una función tal que:
- la magnitud de un número se reduce lo más posible
- todos los números siguen siendo enteros
- sus proporciones relativas permanecen constantes
En otras palabras, quiero eliminar tantos ceros como sea posible sin perder ninguna información que no sea de magnitud absoluta, para que el conjunto se convierta en {1000, 20000, 1234, 1200}
¿Hay un término para esta operación y hay una función eficiente de Python, o debería codificar esto rápidamente?
Editar: Esta solución no es un duplicado porque trata con números singulares: en mi caso, el número de ceros depende del conjunto particular.
Edición 2: Green Cloak Guy proporcionó una solución para mis requisitos exactos, e Illmora, que hace lo que debería haber conceptualizado en primer lugar.
6 respuestas
Dado que todo lo que le importa aquí es la disminución de la magnitud, ¿ha considerado simplemente representar sus números como Decimal
sy luego imprimirlos en notación científica?
from decimal import Decimal
nums = {Decimal(1000000), Decimal(20000000), Decimal(1234000), Decimal(1200000)}
print({str(num.normalize()) for num in nums})
# {'1E+6', '1.2E+6', '2E+7', '1.234E+6'}
Si eso no es razonable para su caso de uso, entonces otra cosa que puede hacer es esencialmente determinar la magnitud máxima por la que puede reducir, y luego reducir esa cantidad. Para magnitudes de 10, esto es bastante simple y puede usar cadenas para hacerlo:
nums = {1000000, 20000000, 1234000, 1200000}
div_factor = 10 ** min(len(str(num)) - len(str(num).rstrip('0')) for num in nums)
reduced_nums = {num / div_factor for num in nums}
# {1000.0, 1234.0, 20000.0, 1200.0}
# you can use integer division `//` instead of true division `/` if you want
Para magnitudes no estándar (por ejemplo, magnitudes de 3), necesitaría ser más creativo y encontrar una manera de calcular de manera eficiente la magnitud más grande por la que puede dividir. Mi ejemplo anterior toma un atajo aquí al verificar cuántos dígitos desaparecen cuando recortamos los ceros finales (que es equivalente a verificar el mayor exponente de 10 que puede dividirse en números enteros). Dado que Python no tiene una forma integrada de imprimir en bases que no son 2, 8, 10 o 16, tendrá que encontrar su propia solución.
Mirando sus requisitos, lo que busca puede hacerse fácilmente dividiendo cada número de entrada por el MCD (mayor denominador común) de todos los números de entrada.
#!/usr/bin/env python3
import math
from functools import reduce
numbers = [1000000, 20000000, 1234000, 1200000]
# Find the greatest common denominator
gcd = reduce(lambda x,y: math.gcd(x,y), numbers)
# Divide each number by the GCD
minimum_numbers = map(lambda x: int(x/gcd), numbers)
print(*minimum_numbers, sep=',')
Con sus números de entrada, produce este resultado:
500,10000,617,600
Debido a las propiedades del GCD, se garantiza que la salida sea el número entero más bajo posible que aún mantiene las proporciones relativas entre cada número.
No sé si hay una manera más eficiente. Yo usaría:
import numpy as np
def reduce(array):
mult = [0.1]*len(array)
while all(item%10 == 0 for item in array):
array = np.multiply(array, mult)
return array
Resultados:
intgrs = (1000000, 20000000, 1234000, 1200000)
print(reduce(intgrs))
Devolverá una matriz numpy con los siguientes valores: [1000 20000 1234 1200]
No tiene bucle anidado o dos bucles que contienen algo de trabajo
from numpy import multiply
intgr = [1000000, 20000000, 1234000, 1200000]
total = str( sum(intgr) )
mgntd = 10 ** ( len(total) - len(total.rstrip('0') ))
reslt = multiply(intgr, [1/mgntd]*len(intgr)).astype(int)
En caso de que no se preocupe por el orden de los elementos establecidos.
sets = {1000000, 20000000, 1234000, 1200000}
max = max([len("".join(map(str, str(i))).rstrip('0')) for i in sets])
new_set = {int(str(i)[:max]) for i in sets} # gives {1000, 1234, 1200, 2000}
No es tan amable, pero funciona.
def trim_zeros(nums):
while 1:
for i in nums:
if str(i)[-1] != "0":
return(nums)
nums=[int(i/10) for i in nums]
Preguntas relacionadas
Nuevas preguntas
python
Python es un lenguaje de programación multipropósito, de tipificación dinámica y de múltiples paradigmas. Está diseñado para ser rápido de aprender, comprender y usar, y hacer cumplir una sintaxis limpia y uniforme. Tenga en cuenta que Python 2 está oficialmente fuera de soporte a partir del 01-01-2020. Aún así, para preguntas de Python específicas de la versión, agregue la etiqueta [python-2.7] o [python-3.x]. Cuando utilice una variante de Python (por ejemplo, Jython, PyPy) o una biblioteca (por ejemplo, Pandas y NumPy), inclúyala en las etiquetas.