Notation scientifique efficace

12

L'autre jour, mon professeur de chimie nous expliquait la notation scientifique (en utilisant un petit nombre et en la multipliant par des puissances de dix pour exprimer plus facilement les grands nombres), ce qui m'a ramené quelques années en arrière lorsque je l'ai apprise. Après avoir appris les bases, nous avions fait un tas de questions mathématiques typiques, dont certaines étaient les suivantes:

Représenter les éléments suivants en notation scientifique:
a) 50000000
b) 120000000000000
c) 900000000000000000000000000000000000000000
d) pi ^ e ^ i ^ j ^ k ^ std :: vector
...
z) 200
...

Et j'ai pensé: "Quoi? On nous a dit que la notation scientifique était utilisée pour rendre l'écriture de grands nombres plus efficace, mais certains cas ne sont pas du tout plus efficaces!"

Considérez le nombre

300

et sa représentation en notation scientifique:

3x10^2

Quoi, la version scientifiquement notée prend en fait plus de place? Nous ne pouvons pas avoir ça maintenant, n'est-ce pas? (L'espace d'écran est précieux.)
Nous pourrions nous déterminer s'il est plus efficace d'écrire un nombre en notation scientifique ou non, ou ...

Tâche

Votre programme ou fonction doit prendre en entrée un seul nombre positif nde taille arbitraire (jusqu'à ce que votre langue prend en charge) et produire la version scientifiquement notée du nombre.
Cependant, si le nombre d'origine n, après suppression des zéros de fin et de la décimale de fin, prend moins ou la même quantité de caractères à afficher que sa version scientifiquement notée, vous devez nplutôt produire ce nombre d'origine .

Votre code doit être aussi court que possible car la sortie doit également être aussi courte que possible.

Caractéristiques

La notation scientifique efficace est définie comme suit:

bx10^e

best le nombre d'entrée divisé de manière appropriée par des puissances de 10 telles que 1 <= b < 10. Ce nombre doit avoir tous les zéros de fin (et le point décimal si nécessaire) supprimés, mais doit avoir la précision du nombre d'origine (jusqu'à la limite du point décimal dans votre langue, bien sûr). C'est-à-dire 90000devient 9, 13.500devient 1.35, 0.000675devient 6.75etc. Si ce nombre contient plus de décimales que votre langue ne peut en gérer, il doit être arrondi à ce nombre maximal de décimales.

eest l'exposant auquel dix est élevé de telle sorte que n = b x 10^e(rappelez-vous que ce nombre doit être négatif si nest inférieur à 1). Ce nombre ne doit pas avoir de zéros à la fin ni de décimale (principalement parce que s'il ne s'agit pas d'un entier, quelque chose ne va pas ...).

Les caractères x10^ doivent rester tels quels dans la chaîne entre bet e.

Cas de test

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

Notation

C'est le , donc le code le plus court en octets gagne.

Autres règles et clarification

  • Les zéros de fin (et / ou la décimale de fin) ne sont pas comptés dans le nombre de caractères du numéro d'entrée d'origine n. Gardez cela à l'esprit pour les cas tels que le cas de test 6
  • Vous pouvez supposer que si le nombre d'entrée est inférieur à 1, il commencera toujours par un 0 en place pour le chiffre des (comme dans les cas de test 5-8).
  • Le numéro d'entrée ne sera jamais négatif
  • Les fonctionnalités intégrées qui rendent ce défi trivial et les failles standard sont interdites
  • Une nouvelle ligne de fin dans la sortie est OK

EDIT
Merci à user81655 d'avoir signalé les cas de test 7 et 8 avec des pouvoirs incorrects de dix. J'ai maintenant corrigé ces problèmes, assurez-vous que votre code les évalue correctement.

MC ΔT
la source
7
Donc, euh, devrais-je demander quelle pi^e^i^j^k^std::vectorserait la sortie d'entrée ?
Geobits
@Geobits Hmm, eh bien, si vous pouvez attribuer une valeur numérique à std :: vector alors peut-être ... Non, seuls les nombres seront présents dans l'entrée (sauf une décimale pour l'entrée en virgule flottante).
MC ΔT
Ce serait beaucoup plus facile et nous e9000 -> 9e3
occuperions
1
@Cyoce J'y ai pensé, mais j'ai vraiment basé ce défi sur la façon dont il est généralement écrit (comme physiquement écrit), ce qui semble être le cas x10^. Et ce serait un peu de retravailler sur la question, qui je ne pense pas que ce soit approprié maintenant qu'il est affiché
MC ΔT
1
@ghosts_in_the_code Elle ne l'était pas, donc "m'a ramené quelques années au moment où je l'ai appris [en cours de mathématiques]"
MC ΔT

Réponses:

4

ES6, 83 81 octets

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

Échoue probablement pour certains cas toStringextrêmes où il insiste sur le format exponentiel.

Edit: sauvé 2 octets grâce à @ user81655.

Neil
la source
Bonne idée. Soit dit en passant, il semble que vous ayez oublié le /à la fin de l'expression régulière.
user81655
Vous pouvez également réorganiser cela légèrement pour économiser 2 octets:x=>(e=s=>s.replace(/e\+?/,'x10^'),z=e(x.toExponential()),y=e(''+x))[z.length]?z:y
user81655
@ user81655 Ah, ce qui s'est passé là-bas, c'est que mon navigateur m'a confondu en enveloppant la longue ligne de telle manière que je pensais qu'une nouvelle ligne s'y était glissée par erreur.
Neil
2

Python 3, 346 342 319 302 octets

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))

Probablement horriblement joué au golf, mais bon, c'est mon premier essai à quelque chose comme ça. C'est difficile à lire, donc ça doit être bon.

Pour autant que je sache, cela devrait fonctionner dans tous les cas, même avec la tendance de Python à convertir automatiquement les nombres au-delà de n'importe quel seuil en notation scientifique (sauf avec ce «e» cool et fantaisiste). Je ne me souviens pas exactement comment je l'ai fait pour pouvoir retourner des numéros de formulaire standard, mais c'est ce qu'il fait.

Reecer6
la source
2

Perl 6, 96 90 octets

J'ai l'impression que cela pourrait être plus court, mais c'est mon meilleur pour l'instant

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

utilisation : assignez ceci à une variable

Ici, il est un peu défait avec un mauvais commentaire:

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.
}
Raccourcis clavier
la source
Échanger $_ <1avec 1>$_et 1 <=* <10avec10>*>=1
Brad Gilbert b2gills
En fait, je voulais le faire hier soir, mais j'ai oublié. Je le mettrai à jour quand je rentrerai
Hotkeys
2

TI BASIC (nspire): 112 octets

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

Explication

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

Convertit l'entrée en notation scientifique avec la fonction format si elle n'est pas déjà dans ce format, car les petites décimales sont automatiquement converties.

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

Trouve la position du fantaisie E qui dénote les exposants et le remplace par "x10 ^".

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

Vérifie quelle sortie est plus grande et renvoie celle optimale. Sauf s'il s'agit d'une petite décimale, qui est plus petite par défaut.

Pavel
la source
0

Python (3,5) 177 octets

Une solution utilisant l'expression régulière

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

Explication

Importation du module regexp

import re

Définition de la fonction lambda à remplacer eparx10^

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

Conversion de la chaîne en notation scientifique

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

Supprimer 0 padding dans la chaîne d'origine

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

comparer la longueur

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

Résultats

>>> [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
la source