Notação científica eficiente

12

Outro dia, meu professor de química estava nos explicando sobre a notação científica (usando um número pequeno e multiplicando-o por potências de dez para expressar números grandes com mais facilidade), o que me trouxe de volta alguns anos depois que a aprendi. Depois de aprender o básico, fizemos várias perguntas típicas de matemática, algumas das quais eram as seguintes:

Represente o seguinte na notação científica:
a) 50000000
b) 120000000000000
c ) 900000000000000000000000000000000000000000
d) pi ^ e ^ i ^ j ^ k ^ std :: vetor
...
z) 200
...

E pensei: "O quê? Disseram-nos que a notação científica era usada para tornar a escrita de grandes números mais eficiente, mas alguns casos não são mais eficientes!"

Considere o número

300

e sua representação na notação científica:

3x10^2

O que, a versão cientificamente notada ocupa realmente mais espaço? Não podemos ter isso agora, podemos? (O espaço na tela é precioso.)
Poderíamos determinar se é mais eficiente em termos de espaço escrever um número em notação científica ou não, ou ...

Tarefa

Seu programa ou função deve ter como entrada um número positivo único nde tamanho arbitrário (até o que o seu idioma suporta) e gerar a versão do número anotada cientificamente.
No entanto, se o número original n, após a remoção dos zeros à direita e da casa decimal à direita, levar menos ou a mesma quantidade de caracteres a serem exibidos que a versão cientificamente notada, você deverá gerar esse número original n.

Seu código precisa ser o mais curto possível, porque a saída também deve ser o mais curta possível.

Especificações

Notação científica eficiente é definida da seguinte forma:

bx10^e

bé o número de entrada dividido adequadamente por potências de 10, de modo que 1 <= b < 10. Esse número deve ter todos os zeros à direita (e o ponto decimal, se necessário) removidos, mas deve ter a precisão do número original (até o limite de pontos decimais no seu idioma, é claro). Ou seja, 90000torna-se 9, 13.500torna-se 1.35, 0.000675torna-se 6.75etc. Se esse número extremidades se contendo mais lugares decimais do que o idioma pode segurar, ele deve ser arredondada para o número máximo de casas decimais.

eé o expoente ao qual dez é aumentado, de modo que n = b x 10^e(lembre-se de que esse número precisa ser negativo se nfor menor que 1). Esse número não deve ter zeros à direita ou uma casa decimal (principalmente porque, se não for um número inteiro, algo está errado ...).

Os caracteres x10^ devem permanecer como estão na sequência entre be e.

Casos de teste

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

Pontuação

Isso é , então o código mais curto em bytes vence.

Outras regras e esclarecimentos

  • Zeros à direita (e / ou casa decimal à direita) não são contados na contagem de caracteres do número de entrada original n. Lembre-se disso em casos como o caso de teste 6
  • Você pode supor que, se o número de entrada for menor que 1, ele sempre começará com um 0 no lugar dos dígitos (como nos casos de teste 5-8).
  • O número de entrada nunca será negativo
  • Built-ins que tornam esse desafio trivial e brechas padrão não são permitidos
  • Uma nova linha à direita na saída está OK

EDIT
Agradecemos ao user81655 por apontar os casos de teste 7 e 8 com poderes incorretos de dez. Eu os corrigi agora, portanto, verifique se o código os avalia corretamente.

MC ΔT
fonte
7
Então, devo perguntar qual seria a saída para entrada pi^e^i^j^k^std::vector?
Geobits 06/02
@ Geobits Hmm, bem, se você pode atribuir um valor numérico para std :: vector, talvez ... Não, apenas números estarão presentes na entrada (exceto uma casa decimal para a entrada de ponto flutuante).
MC ΔT
Isso seria muito mais fácil e que iria ocupar menos do seu "espaço de tela precioso" se usado e: 9000 -> 9e3(quase mais de 9.000 !)
Cyoce
1
@ Cyoce eu pensei sobre isso, mas eu realmente baseei esse desafio na maneira como ele é geralmente escrito (como no escrito fisicamente), o que parece ser x10^. E seria um pouco de retrabalho sobre a questão, que eu não acho que é que apropriado agora que ele postou
MC AT
1
@ghosts_in_the_code Ela não estava, portanto "me trouxe de volta alguns anos para quando eu o aprendi pela primeira vez [na aula de matemática]"
MC ΔT

Respostas:

4

ES6, 83 81 bytes

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

Provavelmente falha em alguns casos toStringextremos onde insiste no formato exponencial.

Editar: salvou 2 bytes graças a @ user81655.

Neil
fonte
Boa ideia. A propósito, parece que você esqueceu o /no final do regex.
user81655
Além disso, você pode reorganizá-lo um pouco para economizar 2 bytes:x=>(e=s=>s.replace(/e\+?/,'x10^'),z=e(x.toExponential()),y=e(''+x))[z.length]?z:y
user81655
@ user81655 Ah, o que aconteceu lá é que meu navegador me confundiu ao envolver a linha longa de maneira que eu pensava que uma nova linha havia entrado lá por engano.
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))

Provavelmente terrivelmente jogado, mas ei, esta é a minha primeira tentativa em algo assim. É difícil de ler, então deve ser bom.

Tanto quanto sei, deve funcionar em todos os casos, mesmo com a tendência do Python de converter automaticamente números além de qualquer limiar em notação científica (exceto com esse e elegante e legal '). Não me lembro exatamente como consegui retornar números de formulários padrão, mas é o que faz.

Reecer6
fonte
2

Perl 6, 96 90 bytes

Eu sinto que isso poderia ser mais curto, mas este é o meu melhor por enquanto

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

uso : atribua isso a uma variável

Aqui está um pouco destruído com alguns comentários ruins:

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 atalho
fonte
Troque $_ <1com 1>$_e 1 <=* <10com10>*>=1
Brad Gilbert b2gills 12/02
Na verdade, eu pretendia fazer isso ontem à noite, mas esqueci. Vou atualizá-lo quando chegar em casa
Teclas de atalho
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

Explicação

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

Converte a entrada em notação científica com a função de formatação, se ela ainda não estiver nesse formato, pois os decimais pequenos são convertidos automaticamente.

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

Encontra a posição da fantasia E que denota expoentes e a substitui por "x10 ^".

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

Verifica qual saída é maior e retorna a melhor. A menos que seja um decimal pequeno, que é menor por padrão.

Pavel
fonte
0

Python (3.5) 177 bytes

Uma solução usando expressão 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

Explicação

Importação do módulo regexp

import re

Definição da função lambda para substituir eporx10^

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

Conversão da corda em notação científica

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

Remova 0 preenchimento na string original

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

comparar comprimento

 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
fonte