Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

147
Views
Python redondea a la siguiente potencia más alta de 10

¿Cómo me las arreglaría para realizar math.ceil de manera que se asigne un número a la siguiente potencia más alta de 10?

 # 0.04 -> 0.1 # 0.7 -> 1 # 1.1 -> 10 # 90 -> 100 # ...

Mi solución actual es un diccionario que verifica el rango del número de entrada, pero está codificado y preferiría una solución de una sola línea. ¿Quizás me estoy perdiendo un truco matemático simple o una función numérica correspondiente aquí?

over 4 years ago · Santiago Trujillo
6 answers
Answer question

0

Puede usar math.ceil con math.log10 para hacer esto:

 >>> 10 ** math.ceil(math.log10(0.04)) 0.1 >>> 10 ** math.ceil(math.log10(0.7)) 1 >>> 10 ** math.ceil(math.log10(1.1)) 10 >>> 10 ** math.ceil(math.log10(90)) 100

log10(n) te da la solución x que satisface 10 ** x == n , así que si redondeas x te da el exponente de la siguiente potencia más alta de 10.

Tenga en cuenta que para un valor n donde x ya es un número entero, la "siguiente potencia más alta de 10" será n :

 >>> 10 ** math.ceil(math.log10(0.1)) 0.1 >>> 10 ** math.ceil(math.log10(1)) 1 >>> 10 ** math.ceil(math.log10(10)) 10
over 4 years ago · Santiago Trujillo Report

0

Su problema está subespecificado, necesita dar un paso atrás y hacer algunas preguntas.

  • ¿De qué tipo(s) son sus entradas?
  • ¿Qué tipo(s) desea para sus productos?
  • Para resultados inferiores a 1, ¿a qué desea redondear exactamente? ¿Quiere potencias de 10 reales o aproximaciones de coma flotante de potencias de 10? ¿Sabes que las potencias negativas de 10 no se pueden expresar exactamente en punto flotante, verdad? Supongamos por ahora que desea aproximaciones de punto flotante de potencias de 10.
  • Si la entrada es exactamente una potencia de 10 (o la aproximación de punto flotante más cercana a una potencia de 10), ¿debe ser la salida igual que la entrada? ¿O debería ser la siguiente potencia de 10? ¿"10 -> 10" o "10 -> 100"? Supongamos lo primero por ahora.
  • ¿Pueden sus valores de entrada ser cualquier valor posible de los tipos en cuestión? o están más limitados.

En otra respuesta, se propuso tomar el logaritmo, luego redondear (función de techo) y luego exponenciar.

 def nextpow10(n): return 10 ** math.ceil(math.log10(n))

Desafortunadamente, esto adolece de errores de redondeo. En primer lugar, n se convierte de cualquier tipo de datos que tenga en un número de coma flotante de doble precisión, lo que podría introducir errores de redondeo, luego se calcula el logaritmo, lo que podría introducir más errores de redondeo tanto en sus cálculos internos como en su resultado.

Como tal, no me llevó mucho tiempo encontrar un ejemplo en el que diera un resultado incorrecto.

 >>> import math >>> from numpy import nextafter >>> n = 1 >>> while (10 ** math.ceil(math.log10(nextafter(n,math.inf)))) > n: ... n *= 10 ... >>> n 10 >>> nextafter(n,math.inf) 10.000000000000002 >>> 10 ** math.ceil(math.log10(10.000000000000002)) 10

También es teóricamente posible que falle en la otra dirección, aunque esto parece mucho más difícil de provocar.

Entonces, para una solución robusta para flotantes e enteros, debemos asumir que el valor de nuestro logaritmo es solo aproximado y, por lo tanto, debemos probar un par de posibilidades. Algo en la línea de

 def nextpow10(n): p = round(math.log10(n)) r = 10 ** p if r < n: r = 10 ** (p+1) return r;

Creo que este código debería dar resultados correctos para todos los argumentos en un rango sensible de magnitudes del mundo real. Se interrumpirá para cantidades muy pequeñas o muy grandes de tipos que no sean enteros ni de coma flotante debido a problemas para convertirlos a coma flotante. Python aplica argumentos enteros especiales a la función log10 en un intento de evitar el desbordamiento, pero aun así, con un entero lo suficientemente masivo, es posible forzar resultados incorrectos debido a errores de redondeo.

Para probar las dos implementaciones, utilicé el siguiente programa de prueba.

 n = -323 # 10**-324 == 0 while n < 1000: v = 10 ** n if v != nextpow10(v): print(str(v)+" bad") try: v = min(nextafter(v,math.inf),v+1) except: v += 1 if v > nextpow10(v): print(str(v)+" bad") n += 1

Esto encuentra muchas fallas en la implementación ingenua, pero ninguna en la implementación mejorada.

over 4 years ago · Santiago Trujillo Report

0

¡Mira esto!

 >>> i = 0.04123 >>> print i, 10 ** len(str(int(i))) if int(i) > 1 else 10 if i > 1.0 else 1 if i > 0.1 else 10 ** (1 - min([("%.100f" % i).replace('.', '').index(k) for k in [str(j) for j in xrange(1, 10) if str(j) in "%.100f" % i]])) 0.04123 0.1 >>> i = 0.712 >>> print i, 10 ** len(str(int(i))) if int(i) > 1 else 10 if i > 1.0 else 1 if i > 0.1 else 10 ** (1 - min([("%.100f" % i).replace('.', '').index(k) for k in [str(j) for j in xrange(1, 10) if str(j) in "%.100f" % i]])) 0.712 1 >>> i = 1.1 >>> print i, 10 ** len(str(int(i))) if int(i) > 1 else 10 if i > 1.0 else 1 if i > 0.1 else 10 ** (1 - min([("%.100f" % i).replace('.', '').index(k) for k in [str(j) for j in xrange(1, 10) if str(j) in "%.100f" % i]])) 1.1 10 >>> i = 90 >>> print i, 10 ** len(str(int(i))) if int(i) > 1 else 10 if i > 1.0 else 1 if i > 0.1 else 10 ** (1 - min([("%.100f" % i).replace('.', '').index(k) for k in [str(j) for j in xrange(1, 10) if str(j) in "%.100f" % i]])) 90 100

Este código se basa en el principio de la potencia de diez en len(str(int(float_number))) .

Hay 4 casos:

    1. int(i) > 1 .

      Número Float : convertido a int , a partir de ahí, la cadena str() nos dará una string con la length que estamos buscando exactamente. Entonces, la primera parte, para la entrada i > 1.0 , es diez 10 en potencia de esta longitud.

    1. & 3. Poca ramificación: i > 1.0 e i > 0.1 <=> es 10 y 1 respectivamente.
    1. Y último caso, cuando i < 0.1 : Aquí, diez estará en potencia negativa. Para obtener el primer elemento distinto de cero después de la coma, he usado dicha construcción ("%.100f" % i).replace('.', '').index(k) , donde k se ejecuta en el intervalo [1:10] . A partir de entonces, tome el mínimo de la lista de resultados. Y disminuir en uno, es el primer cero, que se contará. Además, aquí el index() puede fallar, si no encuentra al menos uno de los elementos distintos de cero del intervalo [1:10] , es por eso que al final debo "filtrar" la lista por ocurrencia: if str(j) in "%.100f" % i . Además, para obtener una precisión más profunda, %.100f puede tomarse de manera diferente.
over 4 years ago · Santiago Trujillo Report

0

Parece que desea más bien la próxima potencia más baja de 10 ... Aquí hay una forma de usar matemáticas puras y sin registro, sino recursividad.

 def ceiling10(x): if (x > 10): return ceiling10(x / 10) * 10 else: if (x <= 1): return ceiling10(10 * x) / 10 else: return 10 for x in [1 / 1235, 0.5, 1, 3, 10, 125, 12345]: print(x, ceiling10(x))
over 4 years ago · Santiago Trujillo Report

0

y = math.ceil(x) z = y + (10 - (y % 10))

¿Algo como esto tal vez? Está fuera de mi cabeza, pero funcionó cuando probé algunos números en la terminal.

over 4 years ago · Santiago Trujillo Report

0

Creo que la forma más sencilla es:

 import math number = int(input('Enter a number: ')) next_pow_ten = round(10 ** math.ceil(math.log10(number))) print(str(10) + ' power ' + str(round(math.log10(number))) + ' = '\ + str(next_pow_ten))

Espero que esto te ayude.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!