สัญลักษณ์ทางวิทยาศาสตร์ที่มีประสิทธิภาพ


12

วันหนึ่งครูสอนเคมีของฉันอธิบายให้เราฟังเกี่ยวกับสัญกรณ์วิทยาศาสตร์ (ใช้จำนวนน้อยและคูณด้วยพลังสิบเพื่อแสดงจำนวนมากได้ง่ายขึ้น) ซึ่งทำให้ฉันกลับมาเมื่อสองสามปีก่อนเมื่อฉันเรียนรู้ หลังจากเรียนรู้พื้นฐานแล้วเราได้ทำคำถามคณิตศาสตร์โดยทั่วไปซึ่งบางคำถามมีลักษณะดังต่อไปนี้:

แสดงสิ่งต่อไปนี้ในสัญกรณ์วิทยาศาสตร์:
a) 50000000
b) 120000000000000
c) 90000000000000000000000000000000000000
d) pi ^ e ^ i ^ 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^ จะต้องยังคงเป็นอยู่ในสตริงระหว่างและbe

กรณีทดสอบ

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)
  • หมายเลขอินพุตจะไม่เป็นค่าลบ
  • บิวด์อินที่ทำให้ความท้าทายนี้ไม่อนุญาตให้มีช่องโหว่เล็กน้อยและมาตรฐาน
  • บรรทัดใหม่ต่อท้ายในผลลัพธ์คือตกลง

แก้ไข
ขอบคุณ user81655 สำหรับการชี้กรณีทดสอบ 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


ความคิดดี. โดยวิธีการดูเหมือนว่าคุณลืม/ปลาย regex
user81655

นอกจากนี้คุณสามารถจัดเรียงใหม่นี้เพื่อบันทึก 2 ไบต์:x=>(e=s=>s.replace(/e\+?/,'x10^'),z=e(x.toExponential()),y=e(''+x))[z.length]?z:y
user81655

@ user81655 อ่าเกิดอะไรขึ้นนั่นคือเบราว์เซอร์ของฉันทำให้ฉันสับสนโดยการพันยาวในลักษณะที่ฉันคิดว่าบรรทัดใหม่พุ่งเข้ามาโดยไม่ได้ตั้งใจ
Neil

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 ที่จะแปลงตัวเลขที่ผ่านเกณฑ์โดยอัตโนมัติให้กลายเป็นสัญลักษณ์ทางวิทยาศาสตร์ (ยกเว้นกับตัวอักษรที่เจ๋งและแฟนซี ฉันจำไม่ได้ว่าฉันทำอย่างนั้นได้อย่างไรเพื่อให้สามารถส่งคืนหมายเลขแบบฟอร์มมาตรฐานได้ แต่เป็นเช่นนั้น


2

Perl 6, 96 90 ไบต์

ฉันรู้สึกว่านี่อาจสั้นกว่านี้ แต่ตอนนี้ฉันดีที่สุดแล้ว

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

การใช้งาน : กำหนดสิ่งนี้ให้กับตัวแปร

นี่มัน ungolfed เล็กน้อยด้วยความเห็นที่ไม่ดี:

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

Swap $_ <1ด้วย1>$_และ1 <=* <10ด้วย10>*>=1
แบรดกิลเบิร์ b2gills

เมื่อคืนนี้ฉันตั้งใจจะทำ แต่ฉันลืมไปแล้ว ฉันจะอัปเดตเมื่อฉันกลับถึงบ้าน
ฮอตคีย์

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 ที่ denotates เลขชี้กำลังและแทนที่ด้วย "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

การกำหนดฟังก์ชัน lambda เพื่อแทนที่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 padding ในสตริงเดิม

 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']
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.