Notasi Ilmiah yang Efisien

12

Suatu hari guru kimia saya menjelaskan kepada kami tentang notasi ilmiah (menggunakan sejumlah kecil dan mengalikannya dengan kekuatan sepuluh untuk mengekspresikan jumlah besar lebih mudah), yang membawa saya kembali beberapa tahun ketika saya pertama kali mempelajarinya. Setelah mempelajari dasar-dasarnya, kami telah melakukan banyak pertanyaan matematika yang khas, beberapa di antaranya seperti berikut:

Mewakili yang berikut dalam notasi ilmiah:
a) 50000000
b) 120000000000000
c) 9000000000000000000000000000000000000000000
d) pi ^ e ^ i ^ j ^ k ^ std :: vektor
...
z) 200
...

Dan saya berpikir, "Apa? Kami diberi tahu bahwa notasi ilmiah digunakan untuk membuat penulisan angka besar lebih efisien, tetapi beberapa kasus sama sekali tidak lebih efisien!"

Pertimbangkan angkanya

300

dan perwakilannya dalam notasi ilmiah:

3x10^2

Apa, versi yang dicatat secara ilmiah ini sebenarnya menghabiskan lebih banyak ruang? Kita tidak bisa memilikinya sekarang, kan? (Ruang layar sangat berharga.)
Kita dapat menentukan sendiri apakah lebih efisien ruang untuk menulis nomor dalam notasi ilmiah atau tidak, atau ...

Tugas

Program atau fungsi Anda harus menggunakan satu nomor positif nukuran arbitrer (hingga apa yang didukung bahasa Anda) sebagai input dan menampilkan versi nomor yang dicatat secara ilmiah.
Namun, jika nomor asli n, setelah menghilangkan nol jejak dan tempat desimal, membutuhkan lebih sedikit atau jumlah karakter yang sama untuk ditampilkan daripada versi yang dicatat secara ilmiah, Anda harus menampilkan nomor asli itu nsebagai gantinya.

Kode Anda harus sesingkat mungkin karena outputnya juga harus sesingkat mungkin.

Spesifikasi

Notasi Ilmiah yang Efisien didefinisikan sebagai berikut:

bx10^e

badalah nomor input dibagi dengan tepat oleh kekuatan 10 sedemikian rupa sehingga 1 <= b < 10. Angka ini harus menghapus semua nol trailing (dan titik desimal jika diperlukan), tetapi harus memiliki ketepatan angka aslinya (tentu saja, hingga batas titik desimal dalam bahasa Anda). Yaitu 90000menjadi 9, 13.500menjadi 1.35, 0.000675menjadi 6.75dll. Jika angka ini akhirnya mengandung lebih banyak tempat desimal daripada bahasa Anda dapat menangani, itu harus dibulatkan ke jumlah tempat desimal maksimum itu.

eadalah eksponen di mana sepuluh dinaikkan sedemikian rupa n = b x 10^e(ingat bahwa angka ini harus negatif jika nlebih kecil dari 1). Angka ini seharusnya tidak memiliki angka nol atau tempat desimal (terutama karena jika bukan bilangan bulat, ada sesuatu yang salah ...).

Karakter x10^ harus tetap seperti dalam string antara bdan e.

Uji kasus

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

Mencetak gol

Ini adalah , jadi kode terpendek dalam byte menang.

Aturan dan klarifikasi lainnya

  • Nol trailing (dan / atau trailing tempat desimal) tidak dihitung terhadap jumlah karakter dari nomor input asli n. Ingatlah itu untuk kasus-kasus seperti test case 6
  • Anda dapat mengasumsikan bahwa jika nomor input kurang dari 1, itu akan selalu mulai dengan 0 di tempat untuk digit tersebut (seperti dalam kasus uji 5-8).
  • Nomor input tidak akan pernah negatif
  • Built-in yang membuat tantangan ini sepele dan celah standar tidak diijinkan
  • Baris baru yang tertinggal di output OK

EDIT
Terima kasih kepada pengguna81655 untuk menunjukkan kasus uji 7 dan 8 memiliki kekuatan sepuluh yang salah. Saya sekarang telah memperbaikinya jadi pastikan kode Anda mengevaluasi mereka dengan benar.

MC ΔT
sumber
7
Jadi, eh, haruskah saya bertanya apa output untuk input pi^e^i^j^k^std::vector?
Geobits
@ Geobits Hmm, yah jika Anda dapat menetapkan nilai numerik ke std :: vector maka mungkin ... Tidak, hanya angka yang akan ada di input (kecuali tempat desimal untuk input floating point).
MC ΔT
Ini akan jauh lebih mudah dan kami akan mengurangi "ruang layar berharga" Anda jika digunakan e: 9000 -> 9e3(hampir lebih dari 9.000 !)
Cyoce
1
@Cyoce Saya memikirkan hal itu, tapi saya benar-benar mendasarkan tantangan ini pada cara umumnya ditulis (seperti dalam tulisan fisik), yang sepertinya ada di sini x10^. Dan itu akan menjadi sedikit adil pada pertanyaan, yang saya pikir tidak sepantasnya sekarang diposting
MC ΔT
1
@ ghosts_in_the_code Dia tidak, karena itu "membawa saya kembali beberapa tahun ketika saya pertama kali mempelajarinya [di kelas matematika]"
MC ΔT

Jawaban:

4

ES6, 83 81 byte

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

Mungkin gagal untuk beberapa kasus tepi di mana toStringbersikeras pada format eksponensial.

Sunting: Disimpan 2 byte berkat @ user81655.

Neil
sumber
Ide bagus. Ngomong-ngomong, sepertinya Anda lupa /pada akhir regex.
user81655
Anda juga dapat mengatur ulang ini sedikit untuk menghemat 2 byte:x=>(e=s=>s.replace(/e\+?/,'x10^'),z=e(x.toExponential()),y=e(''+x))[z.length]?z:y
user81655
@ user81655 Ah, apa yang terjadi di sana adalah browser saya membuat saya bingung dengan membungkus garis panjang sedemikian rupa sehingga saya berpikir bahwa baris baru telah merayap di sana karena kesalahan.
Neil
2

Python 3, 346 342 319 302 byte

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

Mungkin bermain golf yang mengerikan, tapi hei, ini adalah percobaan pertama saya pada sesuatu seperti ini. Sulit dibaca, jadi pasti bagus.

Sejauh yang saya ketahui, ini harus bekerja pada setiap kasus, bahkan dengan kecenderungan Python untuk secara otomatis mengubah angka yang melewati ambang apa pun menjadi notasi ilmiah (kecuali dengan 'e' yang keren dan mewah). Saya tidak ingat persis bagaimana saya membuatnya bisa mengembalikan angka formulir standar, tetapi itu berhasil.

Reecer6
sumber
2

Perl 6, 96 90 byte

Saya merasa ini bisa lebih pendek, tapi ini yang terbaik untuk saat ini

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

penggunaan : Tetapkan ini ke variabel

Ini dia ungolfed sedikit dengan beberapa komentar buruk:

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.
}
Tombol cepat
sumber
Tukar $_ <1dengan 1>$_dan 1 <=* <10dengan10>*>=1
Brad Gilbert b2gills
Sebenarnya aku bermaksud melakukan itu tadi malam tapi aku lupa. Saya akan memperbaruinya ketika saya tiba di rumah
Hotkeys
2

TI BASIC (nspire): 112 byte

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

Penjelasan

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

Mengonversi input ke notasi ilmiah dengan fungsi format jika sudah tidak dalam format tersebut - karena desimal kecil dikonversi secara otomatis.

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

Menemukan posisi fancy E yang menunjukkan eksponen dan menggantinya dengan "x10 ^".

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

Periksa output mana yang lebih besar dan mengembalikan yang optimal. Kecuali jika itu adalah desimal kecil, yang lebih kecil secara default.

Pavel
sumber
0

Python (3.5) 177 byte

Solusi menggunakan ekspresi reguler

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

Penjelasan

Impor modul regexp

import re

Pengganti fungsi lambda untuk menggantikan eolehx10^

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

Konversi string dalam notasi ilmiah

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

Hapus 0 padding dalam string asli

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

bandingkan panjangnya

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

Hasil

>>> [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
sumber