Biorąc pod uwagę wyrażenie, Twoim zadaniem jest jego ocena. Jednak twoja odpowiedź nie może zawierać więcej cyfr niż to konieczne, ponieważ daje to wrażenie posiadania dokładniejszych pomiarów niż rzeczywistość.
Liczba znaczących cyfr, które ma liczba, to liczba cyfr, które zapisano w notacji naukowej, w tym zera na końcu, jeśli występuje przecinek dziesiętny. Na przykład 1200
ma 2 znaczące liczby, ponieważ ma, 1.2*10^3
ale 1200.
ma 4 znaczące liczby i 1200.0
ma 5 znaczących liczb.
Dodając dwie liczby, wynik należy zaokrąglić do tej samej liczby miejsc, co liczba, której najmniej znacząca cyfra znajduje się najdalej w lewo. Na przykład 1200 + 3 = 1200
(zaokrąglone do setek miejsca, ponieważ 1200 jest zaokrąglone do setek miejsc) 1200.01 + 3 = 1203
, i 4.59 + 2.3 = 6.9
. Zauważ, że 5
zaokrągla w górę. Ta sama zasada dotyczy odejmowania. 0
jest zaokrąglony do jednego miejsca. Pamiętaj, że dodawanie i odejmowanie nie zależy od liczby cyfr znaczących. Na przykład,999 + 2.00 = 1001
ponieważ 999 jest zaokrąglone do jednego miejsca, a 2,00 jest zaokrąglone do setnego miejsca; jeden zaokrąglony do mniejszej liczby miejsc to 999, więc wynik 1001,00 również powinien zostać zaokrąglony do jednego miejsca. Podobnie, 300 + 1 - 300 jest dokładnie równe 1, ale 300 jest zaokrąglane do setek miejsc, więc wynik końcowy powinien być również zaokrąglany do setek miejsc, dając 0,300. + 1 - 300. równałoby się 1 na druga ręka.
Mnożąc lub dzieląc dwie liczby, zaokrąglij do liczby cyfr znaczących liczby z cyframi najmniej znaczącymi. Na przykład, 3.839*4=20
ponieważ dokładna wartość 15.356
, zaokrągla do 20
od, 4
ma tylko jedną znaczącą liczbę. Podobnie, 100/4=30
ponieważ obie liczby mają jedną znaczącą liczbę, ale 100./4.00=25.0
ponieważ obie liczby mają 3 znaczące liczby. 0
jest zdefiniowany jako mający 1 znaczącą liczbę.
Ekspresja może zawierać tylko *
, /
, +
i -
(i nawiasów). Kolejność operacji powinna być przestrzegana, a wyniki powinny być zaokrąglane po każdej operacji. Jeśli nawiasy są pominięte w ciągu dodawania lub odejmowania lub ciągu mnożenia i dzielenia, to należy zaokrąglić po zakończeniu wszystkich operacji. Na przykład 6*0.4*2 = 5
(jedna znacząca liczba), podczas gdy 0.4*(2*6)=0.4*10=4
i (6*0.4)*2=2*2=4
.
Dane wejściowe : ciąg znaków z wyrażeniem zawierającym ()*/+-
cyfry. Aby uprościć rzeczy, -
będzie używany tylko jako operator odejmowania, a nie jako liczby ujemne; odpowiedzi mogą jednak być przeczące i wymagać będą -
przedrostka.
Wyjście : Wynikiem wyrażenia, oceniane i zaokrąglona do poprawnej liczby cyfr. Zauważ, że 25
jest niepoprawny dla 25.0
.
Przypadki testowe :
3 + 0.5 --> 4
25.01 - 0.01 --> 25.00
4*7*3 --> 80
(4*7)*3 --> 90
(8.0 + 0.5)/(2.36 - 0.8 - 0.02) --> 5.7
6.0 + 4.0 --> 10.0
5.0 * 2.0 --> 10.0
1/(2.0 * (3.0 + 5.0)) --> 0.06
0.0020 * 129 --> 0.26
300 + 1 - 300 --> 0
0 - 8.8 --> -9
3*5/2*2 --> 20
Edge case: Rozważ problem 501*2.0
. Dokładna wartość to 1002
. Drukowanie 1002
daje zbyt wiele znaczących liczb (4, gdy potrzebujemy 2), ale 1000
daje zbyt mało (1, gdy potrzebujemy 2). W takim przypadku program powinien 1000
mimo to wydrukować .
To źródło wyjaśnia również cyfry znaczące: http://www.purplemath.com/modules/rounding2.htm
999 + 2.00
.300 + 1 - 300
jest ciągiem dodawania i odejmowania, więc nie trzeba go zaokrąglać do końca.(300 + 1) - 300
byłoby zero.Odpowiedzi:
Java 11,
13251379135613361290 bajtów+54 bajtów, aby naprawić wielkość liter
501*2.0
(dawał wynik1002
wcześniej, ale teraz jest poprawny1000
).Rozumiem teraz, dlaczego na to wyzwanie nie udzielono odpowiedzi przez prawie dwa lata ..>.> To wyzwanie ma więcej specjalnych przypadków niż język holenderski, który mówi coś ..
Java z pewnością nie jest odpowiednim językiem dla tego rodzaju wyzwań (lub jakiegokolwiek dorosłego golfa wyzwanie w tej sprawie ...; p), ale jest to jedyny język, który znam wystarczająco dobrze, aby nawet podjąć takie trudne wyzwanie.
Format wejściowy
String
bez spacji (jeśli nie jest to dozwolone, możesz dodaćs=s.replace(" ","")
(+19 bajtów) na górze metody).Wypróbuj online.
Wyjaśnienie:
Przepraszam za długi post.
Ta część służy do wprowadzania danych zawierających nawiasy. Otrzyma oddzielne części i użyje wywołań rekurencyjnych.
0.4*(2*6)
staje się0.4*A
, gdzieA
jest rekurencyjne połączenie zc(2*6)
(8.3*0.02)+(1.*(9*4)+2.2)
staje sięA+B
, gdzieA
jest rekurencyjne połączenie zc(8.3*0.02)
iB
rekurencyjne połączenie zc(1.*(9*4)+2.2)
→ które z kolei staje się1.*C+2.2
, gdzieC
jest połączenie rekurencyjne zc(9*4)
Ta pierwsza pętla służy do wypełnienia wartości
M
orazk
, gdzieM
jest największą długością całkowitą w odniesieniu do liczb znaczących ik
największą długością dziesiętną.1200+3.0
staje sięM=2, k=1
(12, .0
)999+2.00
staje sięM=3, k=2
(999, .00
)300.+1-300.
staje sięM=3, k=0
(300, .
)Ta druga pętla służy do wypełniania tablic,
A
ab
także wartościq
, gdzieA
jest liczba znaczących cyfr, zawierab
liczby całkowite z zerami wiodącymi, aby je dopasowaćM
, iq
jest najmniejszą kropką bez uwzględnienia kropek.1200+3.0
staje sięA=[2, 5] (12, 00030)
,b=[1200, 0003.0]
iq=2
(30
)999+2.00
staje sięA=[3, 5] (999, 00200)
,b=[999, 002.00]
iq=3
(zarówno999
i200
)300.+1-300.
staje sięA=[3, 3, 3] (300, 001, 300)
,b=[300., 001, 300.]
iq=1
(1
)501*2.0
staje sięA=[3, 4] (501, 0020)
,b=[501, 002.0]
iq=2
(20
)Używa silnika JavaScript do oceny danych wejściowych, które zostaną zapisane
R
jako podwójne.1200+3.0
staje sięR=1203.0
999+2.00
staje sięR=1001.0
300.+1-300.
staje sięR=1.0
Ustawia
m
się na najmniejszą wartość w tablicyA
.A=[2, 5]
staje sięm=2
A=[3, 5]
staje sięm=3
A=[3, 3, 3]
staje sięm=3
To zmienia się w
m
oparciu o wiele czynników.999+2.00 = 1001.0
&m=3,q=3
staje sięm=4
(ponieważm==M
(oba3
) →R%1==0
(1001.0
nie ma wartości dziesiętnych) →(int)R/10%10<1
((int)1001.0/10
staje się100
→100%10<1
) →"1001".length()>m
(4>3
) →"1001".length()-q<=1
(4-3<=1
) → więcm
staje się długością części całkowitej"1001"
(4
))3.839*4 = 15.356
&m=1,q=1
pozostajem=1
(ponieważm==M
(oba1
) →R%1!=0
(15.356
ma wartości dziesiętne) →R<=99
→R%10!=0
(15.356%10==5.356
) →m!=0
→ więcm
pozostaje ten sam (1
))4*7*3 = 84.0
&m=1,q=1
pozostajem=1
(ponieważm==M
(oba1
) →R%1==0
(84.0
nie ma wartości dziesiętnych) →(int)R/10%10>=1
((int)84/10
staje się8
→8%10>=1
) →R<=99
→R%10!=0
(84%10==4
) →m!=0
→ więcm
pozostaje taki sam (1
))6.0+4.0 = 10.0
&m=2,q=2
staje sięm=3
(ponieważm!=M
(m=2, M=1
) →R<=99
→R%10==0
(10%10==0
) → więcm
staje się długością sumyR
(minus kropka)"10.0".length()-1
(3
))0-8.8 = -8.8
im=0,q=1
staje sięm=1
(ponieważm!=M
(m=0, M=1
) →R<=99
→R%10!=0
(-8.8%10==-8.8
) →m<1
→m
staje się1
)501*2.0 = 1001.0
&m=3,q=2
staje sięm=2
(ponieważm==M
(oba3
) →R%1==0
(1001.0
nie ma wartości dziesiętnych) →(int)R/10%10<1
((int)1001.0/10
staje się100
→100%10<1
) →"1001".length()>m
(4>3
) →"1001".length()-q>1
(4-2>1
) → więcm
staje sięq
(2
))Teraz
R
jest zaokrąglany na podstawiem
.1001.0
im=4
staje się1001.0
0.258
Im=3
staje się0.26
(ze względuabs(R)<1
,m-1
(2
), a niem=3
są stosowane wewnątrzMathContext
)-8.8
im=1
staje się-9.0
1002.0
im=2
staje się1000.0
W
R
razie potrzeby modyfikuje to część całkowitą .300.+1-300. = 1.0
im=3,M=3
zostaje1.0
(ponieważm>=M
→ więcR
pozostaje taki sam (1.0
))0.4*10 = 4.0
im=1,M=2
zostaje4.0
(ponieważm<M
→(10^(M-m))/10<=R
((10^1)/10<=4.0
→10/10<=4.0
→1<=4.0
) → więcR
pozostaje ten sam (4.0
))300+1-300 = 1.0
&m=1,M=3
staje się0.0
(ponieważm<M
→(10^(M-m))/10>R
((10^2)/10>1.0
→100/10>1.0
→10>1.0
) →R
staje się z0.0
powoduint(R/(10^(M-m)))*(10^(M-m))
(int(1.0/(10^2))*(10^2)
→int(1.0/100)*100
→0*100
→0
)Ustawia
R
sięr
na String i modyfikuje go na podstawie wielu czynników.1203.0
&m=4,k=2
staje się1203.
(ponieważk>=1
→ takr
staje się1001.000
;r.length()>=m
(8>=4
) →r.contains(".")
→r.length()>=m
(8>=4
) → podciąg z indeksu0
dom+1
(5
))6.9
&m=2,k=2
pozostaje6.9
(ponieważk>=1
→ takr
staje się6.900
;r.length()>=m
(5>=2
) →r.contains(".")
→r.length()>=m
(5>=2
) → podciąg z indeksu0
dom+1
(3
))1.0
&m=3,k=0
staje się1
(ponieważk<1
→ takr
staje się1
;r.length()<m
(1<3
) → podciąg od indeksu0
dor.length()
(1
))25.0
&m=4,k=4
staje się25.00
(ponieważk>=1
→ takr
staje się25.00000
;r.length()>=m
(8>=4
) →r.contains(".")
→r.length()>+m
(8>=4
) → podciąg z indeksu0
dom+1
(5
))0
&m=1,k=0
pozostaje0
(ponieważk<1
→ takr
zostaje0
;r.length()>=m
(1>=1
) →!r.contains(".")
→ podciąg z indeksu0
dom
(1
))Powoduje to, że w razie potrzeby końcowe zera są ponownie częścią liczby całkowitej.
r="12"
iR=1200.0
staje sięr="1200"
r="1"
iR=10.0
staje sięr="10"
r="8"
iR=80.0
staje sięr="80"
I w końcu zwracamy wynik, po usunięciu kropek końcowych.
1203.
staje się1203
5.
staje się5
Zdecydowanie można go pograć w golfa o kilkaset bajtów, ale cieszę się, że teraz działa. Zrozumienie każdego z przypadków i tego, o co pytano w wyzwaniu, zajęło już trochę czasu. A potem zajęło dużo prób i błędów, testów i ponownych testów, aby uzyskać powyższy wynik. Podczas pisania powyższego wyjaśnienia udało mi się usunąć kolejne ± 50 bajtów nieużywanego kodu.
źródło
501*2.0
do wyjścia1000
(i tak powinieneś1000
to zrobić, co interpretuję jako „nadal”, a nie w żadnym wypadku ). I tak wspaniała praca.