Ефективне наукове позначення


12

Днями мій викладач хімії пояснював нам наукові позначення (використовуючи невелику кількість і множивши її на сили десять, щоб легше виразити велику кількість), що повернуло мене кілька років назад, коли я вперше дізнався це. Вивчивши основи, ми зробили купу типових питань з математики, деякі з яких були такі:

У науковій позначці представіть наступне:
а) 50000000
б)
120000000000000 в) 90000000000000000000000000000000000000
г) пі ^ е ^ я ^ j ^ k ^ std :: вектор
...
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).
  • Число введення ніколи не буде від’ємним
  • Вбудовані модулі, які роблять цей виклик тривіальним, а стандартні лазівки заборонені
  • Зворотний новий рядок у виводі

EDIT
Завдяки користувачеві81655 за вказівку тестових випадків 7 та 8 мали неправильні повноваження десять. Зараз я виправив їх, тому переконайтеся, що ваш код правильно їх оцінює.


7
Так що, я повинен запитати, який би був вихід для введення pi^e^i^j^k^std::vector?
Геобіт

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

Це було б набагато простіше, і ми б зайняли менше вашого «дорогоцінного простору екрану», якби він використовував e: 9000 -> 9e3(майже понад 9000 !)
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.


Хороша ідея. До речі, схоже, ви забули /кінець регулярного виразка.
користувач81655

Також ви можете трохи змінити їх, щоб зберегти 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

Пояснення

Імпорт модуля regexp

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.