Notación científica eficiente

12

El otro día, mi profesor de química nos estaba explicando acerca de la notación científica (usando un número pequeño y multiplicándolo por potencias de diez para expresar números grandes con mayor facilidad), lo que me llevó unos años a cuando lo aprendí por primera vez. Después de aprender los conceptos básicos, hicimos un montón de preguntas típicas de matemáticas, algunas de las cuales fueron las siguientes:

Representa lo siguiente en notación científica:
a) 50000000
b) 120000000000000
c) 90000000000000000000000000000000000000
d) pi ^ e ^ i ^ j ^ k ^ std :: vector
...
z) 200
...

Y pensé: "¿Qué? ¡Nos dijeron que la notación científica se usaba para que la escritura de grandes números fuera más eficiente, pero algunos casos no son más eficientes en absoluto!"

Considera el número

300

y su representación en notación científica:

3x10^2

¿Qué, la versión científicamente notada realmente ocupa más espacio? No podemos tener eso ahora, ¿verdad? (El espacio en la pantalla es precioso.)
Podríamos determinar si es más eficiente el espacio para escribir un número en notación científica o no, o ...

Tarea

Su programa o función debe tomar como entrada un único número positivo nde tamaño arbitrario (hasta lo que admite su idioma) y generar la versión del número con notación científica.
Sin embargo, si el número original n, después de eliminar los ceros al final y el lugar decimal al final, toma menos o la misma cantidad de caracteres para mostrar que su versión notada científicamente, debe generar ese número original n.

Su código debe ser lo más corto posible porque la salida también debe ser lo más corta posible.

Especificaciones

La notación científica eficiente se define de la siguiente manera:

bx10^e

bes el número de entrada apropiadamente dividida por potencias de 10 de tal manera que 1 <= b < 10. Este número debe tener todos los ceros finales (y el punto decimal si es necesario) eliminado, pero debe tener la precisión del número original (hasta el límite del punto decimal en su idioma, por supuesto). Es decir, 90000se vuelve 9, 13.500vuelve 1.35, 0.000675vuelve 6.75, etc Si este número hasta extremos que contiene más lugares decimales de la lengua puede manejar, que deben redondearse a ese número máximo de cifras decimales.

ees el exponente al que se eleva diez de tal manera n = b x 10^e(recuerde que este número debe ser negativo si nes menor que 1). Este número no debe tener ceros a la izquierda o un lugar decimal (principalmente porque si no es un entero, algo está mal ...).

Los caracteres x10^ deben permanecer como están en la cadena entre by e.

Casos de prueba

Input -> output
1 -> 1
20 -> 20
3000000 -> 3x10^6
400000 -> 400000
0.008093 -> 0.008093
0.007835000000000 -> 0.007835
0.000003000000 -> 3x10^-6
0.00000065 -> 6.5x10^-7
0 -> 0

Puntuación

Este es el , por lo que gana el código más corto en bytes.

Otras reglas y aclaraciones

  • Los ceros finales (y / o el lugar decimal final) no se cuentan para el recuento de caracteres del número de entrada original n. Tenga esto en cuenta para casos como el caso de prueba 6
  • Puede suponer que si el número de entrada es menor que 1, siempre comenzará con un 0 en lugar de los dígitos (como en los casos de prueba 5-8).
  • El número de entrada nunca será negativo
  • Las incorporaciones que hacen que este desafío sea trivial y las lagunas estándar no están permitidas
  • Una nueva línea final en la salida está bien

EDITAR
Gracias a user81655 por señalar que los casos de prueba 7 y 8 tenían potencias incorrectas de diez. Ahora los he arreglado, así que asegúrese de que su código los evalúe correctamente.

MC ΔT
fuente
77
Entonces, ¿debería preguntar cuál sería la salida para la entrada pi^e^i^j^k^std::vector?
Geobits
@Geobits Hmm, bueno, si puede asignar un valor numérico a std :: vector, entonces tal vez ... No, solo los números estarán presentes en la entrada (excepto un lugar decimal para la entrada de punto flotante).
MC ΔT
Esto sería mucho más fácil y ocuparíamos menos de su "precioso espacio de pantalla" si se usara e: 9000 -> 9e3(¡casi más de 9,000 !)
Cyoce,
1
@Cyoce Pensé en eso, pero realmente basé este desafío en la forma en que generalmente se escribe (como está escrito físicamente), lo que parece estar bien x10^. Y sería un poco de revisión de la cuestión, lo cual no creo que sea apropiado ahora que se publicó
MC ΔT
1
@ghosts_in_the_code Ella no estaba, por lo tanto "me trajo de vuelta unos años antes de que lo aprendiera [en la clase de matemáticas]"
MC ΔT

Respuestas:

4

ES6, 83 81 bytes

x=>(e=s=>s.replace(/e\+?/,'x10^'),z=e(x.toExponential()),y=e(''+x))[z.length]?z:y

Probablemente falla en algunos casos toStringextremos donde insiste en el formato exponencial.

Editar: Guardado 2 bytes gracias a @ user81655.

Neil
fuente
Buena idea. Por cierto, parece que olvidaste el /al final de la expresión regular.
user81655
También podría reorganizar esto ligeramente para ahorrar 2 bytes:x=>(e=s=>s.replace(/e\+?/,'x10^'),z=e(x.toExponential()),y=e(''+x))[z.length]?z:y
user81655
@ user81655 Ah, lo que sucedió allí es que mi navegador me confundió al envolver la línea larga de tal manera que pensé que una nueva línea se había introducido allí por error.
Neil
2

Python 3, 346 342 319 302 bytes

L=len;N=str(float(input()))
if N.endswith('.0'):N=N[:-2]
if'e'in N:C,P=N.split('e');N=N.replace('e','x10^')
else:
 C=N.strip('.0').replace('.','');F=N.find('.')
 if L(C)>1:C=C[0]+'.'+C[1:]
 P=((L(N) if F==-1 else F)-1-N.lstrip('0').find(C[0]))
print(min([N,'{0}x10^{1}'.format(C,int(P))],key=L))

Probablemente jugaron al golf horriblemente, pero bueno, este es mi primer intento en algo como esto. Es difícil de leer, por lo que debe ser bueno.

Hasta donde sé, debería funcionar en todos los casos, incluso con la tendencia de Python de convertir automáticamente los números más allá de cualquier umbral en notación científica (excepto con esa 'e' genial y elegante). No recuerdo exactamente cómo hice para poder devolver números de formulario estándar, pero lo hace.

Reecer6
fuente
2

Perl 6, 96 90 bytes

Siento que esto podría ser más corto, pero esto es lo mejor por ahora

{my \s=($_,*×(1>$_??10!!.1)…10>*>=1);min(s[*-1]~"x10^"~(1>$_??1-s!!s-1),$_,by=>&chars)}

uso : Asigne esto a una variable

Aquí está ungolfed con algunos malos comentarios:

my &f = -> $n {
    my $a = 1 > $n ?? 10 !! .1;             # If $n < 1, we will multiply by 10
                                            # in the sequence below, else by 0.1

    my @seq = ($n, * × $a ... 10 > * >= 1); # Sequence starting at $n, 
                                            # multiply the previous value by $a
                                            # until we reach a number 1 <= x < 10

    # Join the last element in @seq, "x10^", and the length of @seq,
    # with an extra subtraction for numbers less than 1.
    # this gets us our scientific notation.
    my $science = @seq[*-1] ~ "x10^" ~ @seq - (1 > $n ?? @seq*2 !! 1); 

    min($science, $n, by => &chars) # Uses the &chars function to
                                    # choose a min value and return it.
}
Teclas de acceso rápido
fuente
Intercambiar $_ <1con 1>$_y 1 <=* <10con10>*>=1
Brad Gilbert b2gills
En realidad tenía la intención de hacer eso anoche pero lo olvidé. Voy a actualizar cuando llegue a casa
Teclas de acceso directo
2

TI BASIC (nspire): 112 bytes

Define f(x)=
Prgm
string(x)➝a
If x≥1 Then
format(x,"s")➝a
EndIf
instring(a,"ᴇ")➝b
left(a,b-1)&"x10^"&mid(a,b+1)➝a
If dim(a)<dim(string(n)) or x<1 Then
Disp a
Else
Disp x
Endif
EndPrgm

Explicación

If x≥1 Then
format(x,"s")➝a
EndIf

Convierte la entrada a notación científica con la función de formato si ya no está en ese formato, ya que los decimales pequeños se convierten automáticamente.

instring(a,"ᴇ")➝b
left(a,b-1)&"x10^"&mid(a,b+1)➝a

Encuentra la posición de la fantasía E que denota exponentes y la reemplaza con "x10 ^".

If dim(a)<dim(string(x)) or x<1 Then
Disp a
Else
Disp x
Endif

Comprueba qué salida es más grande y devuelve la óptima. A menos que sea un decimal pequeño, que son más pequeños por defecto.

Pavel
fuente
0

Python (3.5) 177 bytes

Una solución usando expresión regular

import re
g=lambda s:re.sub(r"e\+?(-?)0?","x10^\\1",s)
def f(i):
 t=g(re.sub(r"\.[0]*e","e","%e"%i))
 u=g(re.sub(r"(\..*)[0]*$","\\1",str(i)))
 return t if len(u)>len(t) else u

Explicación

Importación del módulo regexp

import re

Definición de la función lambda para reemplazar eporx10^

g=lambda s:re.sub("e\+?(-?)0?","x10^\\1",s)
def f(i):

Conversión de la cadena en notación científica.

 t=g(re.sub(r"\.[0]*e","e","%e"%i))

Eliminar 0 relleno en la cadena original

 u=g(re.sub(r"(\..*)[0]*$","\\1",str(i)))

comparar longitud

 return t if len(u)>len(t) else u

Resultados

>>> [f(i) for i in [1, 20, 3000000, 400000, 0.008093, 0.007835000000000, 0.000003000000, 0.00000065, 0]]
['1', '20', '3x10^6', '400000', '0.008093', '0.007835', '3x10^-6', '6.5x10^-7', '0']
Erwan
fuente