Эффективная научная запись


12

На днях мой учитель химии объяснял нам научную нотацию (используя небольшое число и умножая ее на десятикратные числа, чтобы легче выразить большие числа), что вернуло меня на несколько лет назад, когда я впервые выучил это. Изучив основы, мы выполнили несколько типичных математических вопросов, некоторые из которых были похожи на следующие:

Представьте следующее в научной записи:
а) 50000000
б) 120000000000000
в) 90000000000000000000000000000000000000
г) пи ^ е ^ я ^ j ^ k ^ std :: vector
...
z) 200
...

И я подумал: «Что? Нам сказали, что научная нотация использовалась, чтобы сделать написание больших чисел более эффективным, но некоторые случаи вовсе не более эффективны!»

Считайте число

300

и его представление в научной записи:

3x10^2

Что, научно записанная версия на самом деле занимает больше места? Мы не можем иметь это сейчас, не так ли? (Пространство экрана драгоценно.)
Мы могли бы сами определить, является ли более эффективным использование пространства для записи числа в научной записи или нет, или ...

задача

Ваша программа или функция должны принимать в качестве входных данных одно положительное число nпроизвольного размера (до того, что поддерживает ваш язык) и выводить версию номера с научной точки зрения.
Однако, если исходное число nпосле удаления конечных нулей и конечного десятичного знака занимает меньше или такое же количество символов для отображения, чем его версия с научной нотацией, вы должны nвместо этого вывести это исходное число .

Ваш код должен быть как можно короче, потому что вывод также должен быть максимально коротким.

Характеристики

Эффективная научная нотация определяется следующим образом:

bx10^e

bявляется входным числом, соответствующим образом разделенным на степени 10, так что 1 <= b < 10. У этого числа должны быть удалены все конечные нули (и десятичная точка, если требуется), но должна быть точность исходного числа (конечно, до предела десятичной точки на вашем языке). То есть 90000становится 9, 13.500становится 1.35, 0.000675становится 6.75и т. Д. Если это число содержит больше десятичных знаков, чем может обработать ваш язык, оно должно быть округлено до максимального числа десятичных знаков.

eэто показатель, к которому прибавляется десятка, так что n = b x 10^e(помните, что это число должно быть отрицательным, если nоно меньше 1). Это число не должно иметь конечных нулей или десятичных разрядов (главным образом потому, что если это не целое число, то что-то не так ...).

Символы x10^ должны оставаться как есть в строке между bи e.

Контрольные примеры

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

счет

Это , поэтому выигрывает самый короткий код в байтах.

Другие правила и разъяснения

  • Конечные нули (и / или конечный десятичный знак) не засчитываются в счетчик символов исходного входного числа n. Имейте это в виду для таких случаев, как контрольный пример 6
  • Вы можете предположить, что если введенное число меньше 1, оно всегда будет начинаться с 0 для цифры (как в тестовых примерах 5-8).
  • Входной номер никогда не будет отрицательным
  • Встроенные модули, которые делают эту задачу тривиальной, и стандартные лазейки запрещены
  • Завершающий перевод строки в выводе в порядке

РЕДАКТИРОВАТЬ
Спасибо пользователю 81655 за указание на контрольные примеры 7 и 8 имели неправильные полномочия десять. Я исправил их, поэтому убедитесь, что ваш код правильно их оценивает.


7
Итак, я должен спросить, какой будет выход для ввода pi^e^i^j^k^std::vector?
Geobits

@ Geobits Хм, хорошо, если вы можете назначить числовое значение для std :: vector, тогда, возможно ... Нет, только входные данные будут присутствовать на входе (кроме десятичного знака для ввода с плавающей запятой).
MC ΔT

Это было бы намного проще, и мы бы заняли меньше вашего «драгоценного места на экране», если бы оно использовало e: 9000 -> 9e3(почти более 9 000 !)
Cyoce

1
@Cyoce Я думал об этом, но я действительно основывал эту проблему на том, как она написана (как написано физически), что, похоже, и есть x10^. И это было бы довольно доработкой по этому вопросу, который я не считаю уместным сейчас, когда он был опубликован
MC ΔT

1
@ghosts_in_the_code Она не была, поэтому «вернула меня на несколько лет назад, когда я впервые узнал это [на уроке математики]»
MC ΔT

Ответы:


4

ES6, 83 81 байт

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

Вероятно, терпит неудачу для некоторых крайних случаев, когда toStringнастаивает на экспоненциальном формате.

Редактировать: 2 байта сохранены благодаря @ user81655.


Хорошая идея. Кстати, похоже, что вы забыли /в конце регулярного выражения.
user81655

Также вы можете немного изменить это, чтобы сэкономить 2 байта:x=>(e=s=>s.replace(/e\+?/,'x10^'),z=e(x.toExponential()),y=e(''+x))[z.length]?z:y
user81655

@ user81655 Ах, случилось то, что мой браузер сбил меня с толку, обернув длинную строку таким образом, что я подумал, что новая строка попала туда по ошибке.
Нил

2

Python 3 346 342 319 302 байта

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

Наверное, ужасно в гольф, но эй, это моя первая попытка чего-то подобного. Трудно читать, поэтому должно быть хорошо.

Насколько я знаю, он должен работать в каждом случае, даже с учетом тенденции Python автоматически преобразовывать числа, превышающие любой порог, в научную нотацию (за исключением этого крутого и причудливого 'e'). Я не помню точно, как я сделал это, чтобы иметь возможность возвращать стандартные номера форм, но это делает это.


2

Perl 6, 96 90 байт

Я чувствую, что это может быть короче, но это мое лучшее на данный момент

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

использование : назначьте это переменной

Здесь это немного раскошелилось с некоторыми плохими комментариями:

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.
}

Обмен $_ <1с 1>$_и 1 <=* <10с10>*>=1
Брэд Гилберт b2gills

Я действительно хотел сделать это прошлой ночью, но я забыл. Я обновлю его, когда вернусь домой
Hotkeys

2

TI BASIC (nspire): 112 байт

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

объяснение

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

Преобразует ввод в научную нотацию с помощью функции форматирования, если она уже не находится в этом формате, поскольку небольшие десятичные числа автоматически преобразуются.

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

Находит позицию необычной E, которая обозначает экспоненты и заменяет ее на «x10 ^».

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

Проверяет, какой вывод больше, и возвращает оптимальный. Если это не десятичное число, которое по умолчанию меньше.


0

Python (3.5) 177 байт

Решение с использованием регулярного выражения

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

объяснение

Импорт модуля регулярных выражений

import re

Определение лямбда-функции для замены eнаx10^

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

Конвертация строки в научном обозначении

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

Удалить 0 отступов в оригинальной строке

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

сравнить длину

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

Результаты

>>> [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']
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.