Dada uma expressão, sua tarefa é avaliá-la. No entanto, sua resposta não pode mostrar mais dígitos do que o necessário, pois isso dá a impressão de ter medidas mais precisas do que a realidade.
O número de algarismos significativos que um número possui é quantos dígitos possui quando escritos em notação científica, incluindo zeros no final se houver um ponto decimal. Por exemplo, 1200
possui 2 números significativos porque é, 1.2*10^3
mas 1200.
possui 4 números significativos e 1200.0
5 valores significativos.
Ao adicionar dois números, o resultado deve ser arredondado para o mesmo número de lugares que o número cujo dígito menos significativo está mais à esquerda. Por exemplo, 1200 + 3 = 1200
(arredondado para a casa das centenas desde 1200 é arredondado para a casa das centenas),, 1200.01 + 3 = 1203
e 4.59 + 2.3 = 6.9
. Observe que 5
arredondamentos para cima. Essa mesma regra se aplica à subtração. 0
é arredondado para o local Observe que a adição e subtração não depende do número de dígitos significativos. Por exemplo,999 + 2.00 = 1001
porque 999 é arredondado para o primeiro lugar e 2,00 é arredondado para o centésimo lugar; o que é arredondado para menos lugares é 999; portanto, o resultado, 1001,00, também deve ser arredondado para o local. Da mesma forma, 300 + 1 - 300 é exatamente igual a 1, mas 300 é arredondado para a casa das centenas, portanto o resultado final também deve ser arredondado para a casa das centenas, resultando em 0. 300. + 1 - 300. seria igual a 1 na outra mão.
Ao multiplicar ou dividir dois números, arredonde para o número de dígitos significativos do número com os dígitos menos significativos. Por exemplo, 3.839*4=20
porque o valor exato,, 15.356
arredonda para 20
desde, 4
tem apenas um número significativo. Da mesma forma, 100/4=30
uma vez que ambos os números têm um número significativo, mas 100./4.00=25.0
como ambos os números têm 3 números significativos. 0
está definido para ter 1 figura significativa.
Expressões conterá somente *
, /
, +
, e -
, (e parênteses). A ordem das operações deve ser seguida e os resultados devem ser arredondados após cada operação. Se os parênteses forem deixados de fora em uma sequência de adições ou subtrações ou em uma sequência de multiplicações e divisões, arredonde após todas as operações serem concluídas. Por exemplo, 6*0.4*2 = 5
(uma figura significativa), enquanto 0.4*(2*6)=0.4*10=4
e (6*0.4)*2=2*2=4
.
Entrada : uma sequência, com uma expressão contendo ()*/+-
e dígitos. Para simplificar, -
será usado apenas como operador de subtração, não para significar números negativos; as respostas, no entanto, ainda podem ser negativas e exigiriam -
como prefixo.
Saída : o resultado da expressão, avaliado e arredondado para o número correto de dígitos. Observe que 25
está incorreto para 25.0
.
Casos de teste :
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
Caso de borda: considere o problema de 501*2.0
. O valor exato é 1002
. A impressão 1002
fornece muitos números significativos (4, quando precisamos de 2), mas 1000
fornece muito poucos (1, quando precisamos de 2). Nesse caso, seu programa deve imprimir de 1000
qualquer maneira.
Esta fonte também explica dígitos significativos: http://www.purplemath.com/modules/rounding2.htm
999 + 2.00
,.300 + 1 - 300
é uma série de adições e subtrações, por isso não precisa ser arredondada até o final.(300 + 1) - 300
seria zero.Respostas:
Java 11,
13251379135613361290 bytes+54 bytes para corrigir o caso de borda
501*2.0
(deu o resultado1002
antes, mas agora está correto1000
).Agora eu entendo por que este desafio foi respondida por quase dois anos ..>.> Este desafio tem casos mais especial do que a língua holandesa, que está dizendo algo ..
Java não é certamente a linguagem certa para este tipo de desafios (ou qualquer codegolf desafio nesse sentido ..; p), mas é a única linguagem que conheço o suficiente para tentar um desafio difícil como esse.
Formato de entrada como
String
sem espaços (se isso não for permitido, você pode adicionars=s.replace(" ","")
(+19 bytes) na parte superior do método).Experimente online.
Explicação:
Desculpe pelo longo post.
Esta parte é usada para entrada contendo parênteses. Ele obterá as partes separadas e usará chamadas recursivas.
0.4*(2*6)
torna-se0.4*A
, ondeA
é uma chamada recursiva parac(2*6)
(8.3*0.02)+(1.*(9*4)+2.2)
torna-seA+B
, ondeA
é uma chamada recursivac(8.3*0.02)
eB
uma chamada recursiva parac(1.*(9*4)+2.2)
→ que por sua vez se torna1.*C+2.2
, ondeC
é uma chamada recursiva parac(9*4)
Esse primeiro loop é usado para preencher os valores
M
ek
, ondeM
é o maior comprimento inteiro em relação a números significativos ek
o maior comprimento decimal.1200+3.0
torna-seM=2, k=1
(12, .0
)999+2.00
torna-seM=3, k=2
(999, .00
)300.+1-300.
torna-seM=3, k=0
(300, .
)Esse segundo loop é usado para preencher as matrizes
A
eb
também o valorq
, ondeA
é a quantidade de números significativos,b
mantém os números inteiros com zeros à esquerda correspondentesM
eq
é o menor comprimento, independentemente dos pontos.1200+3.0
torna-seA=[2, 5] (12, 00030)
,b=[1200, 0003.0]
eq=2
(30
)999+2.00
torna-seA=[3, 5] (999, 00200)
,b=[999, 002.00]
eq=3
(ambos999
e200
)300.+1-300.
torna-seA=[3, 3, 3] (300, 001, 300)
,b=[300., 001, 300.]
eq=1
(1
)501*2.0
torna-seA=[3, 4] (501, 0020)
,b=[501, 002.0]
eq=2
(20
)Usa um mecanismo JavaScript para avaliar a entrada, que será salva
R
como o dobro.1200+3.0
torna-seR=1203.0
999+2.00
torna-seR=1001.0
300.+1-300.
torna-seR=1.0
Isso define
m
o menor valor na matrizA
.A=[2, 5]
torna-sem=2
A=[3, 5]
torna-sem=3
A=[3, 3, 3]
torna-sem=3
Isso é modificado com
m
base em vários fatores.999+2.00 = 1001.0
&m=3,q=3
torna - sem=4
(porquem==M
(ambos3
) →R%1==0
(1001.0
não possui valores decimais) →(int)R/10%10<1
((int)1001.0/10
torna-se100
→100%10<1
) →"1001".length()>m
(4>3
) →"1001".length()-q<=1
(4-3<=1
) →m
torna-se o comprimento da parte inteira"1001"
(4
))3.839*4 = 15.356
&m=1,q=1
permanecem=1
(porquem==M
(ambos1
) →R%1!=0
(15.356
tem valores decimais) →R<=99
→R%10!=0
(15.356%10==5.356
) →m!=0
→m
permanece o mesmo (1
))4*7*3 = 84.0
&m=1,q=1
permanecem=1
(porquem==M
(ambos1
) →R%1==0
(84.0
não possui valores decimais) →(int)R/10%10>=1
((int)84/10
torna-se8
→8%10>=1
) →R<=99
→R%10!=0
(84%10==4
) →m!=0
→m
permanece o mesmo (1
))6.0+4.0 = 10.0
&m=2,q=2
torna - sem=3
(porquem!=M
(m=2, M=1
) →R<=99
→R%10==0
(10%10==0
) →m
torna-se o comprimento do totalR
(menos o ponto)"10.0".length()-1
(3
))0-8.8 = -8.8
&m=0,q=1
torna - sem=1
(porquem!=M
(m=0, M=1
) →R<=99
→R%10!=0
(-8.8%10==-8.8
) →m<1
→m
torna - se1
)501*2.0 = 1001.0
&m=3,q=2
torna - sem=2
(porquem==M
(ambos3
) →R%1==0
(1001.0
não possui valores decimais) →(int)R/10%10<1
((int)1001.0/10
torna-se100
→100%10<1
) →"1001".length()>m
(4>3
) →"1001".length()-q>1
(4-2>1
) →m
torna - seq
(2
))Agora
R
é arredondado com base emm
.1001.0
em=4
se torna1001.0
0.258
&m=3
torna - se0.26
(porqueabs(R)<1
,m-1
(2
) em vez dem=3
é usado dentroMathContext
)-8.8
em=1
se torna-9.0
1002.0
em=2
se torna1000.0
Isso modifica a parte inteira,
R
se necessário.300.+1-300. = 1.0
&m=3,M=3
permanece1.0
(porquem>=M
→R
permanece o mesmo (1.0
))0.4*10 = 4.0
&m=1,M=2
permanece4.0
(porquem<M
→(10^(M-m))/10<=R
((10^1)/10<=4.0
→10/10<=4.0
→1<=4.0
) →R
permanece o mesmo (4.0
))300+1-300 = 1.0
&m=1,M=3
torna - se0.0
(porquem<M
→(10^(M-m))/10>R
((10^2)/10>1.0
→100/10>1.0
→10>1.0
) →R
torna - se0.0
por causa deint(R/(10^(M-m)))*(10^(M-m))
(int(1.0/(10^2))*(10^2)
→int(1.0/100)*100
→0*100
→0
)Isso define
R
ar
como corda, e modifica-lo com base em vários fatores.1203.0
&m=4,k=2
torna - se1203.
(porquek>=1
→r
torna - se assim1001.000
;r.length()>=m
(8>=4
) →r.contains(".")
→r.length()>=m
(8>=4
) → substring do índice0
param+1
(5
))6.9
&m=2,k=2
permanece6.9
(porquek>=1
→r
se torna6.900
;r.length()>=m
(5>=2
) →r.contains(".")
→r.length()>=m
(5>=2
) → subcadeia do índice0
param+1
(3
))1.0
&m=3,k=0
torna - se1
(porquek<1
→r
torna - se assim1
;r.length()<m
(1<3
) → substring do índice0
parar.length()
(1
))25.0
&m=4,k=4
torna - se25.00
(porquek>=1
→r
torna - se assim25.00000
;r.length()>=m
(8>=4
) →r.contains(".")
→r.length()>+m
(8>=4
) → substring do índice0
param+1
(5
))0
&m=1,k=0
permanece0
(porquek<1
→r
permanece assim0
;r.length()>=m
(1>=1
) →!r.contains(".")
→ substring do índice0
param
(1
))Isso coloca os zeros à direita novamente na parte inteira, se necessário.
r="12"
eR=1200.0
se tornar="1200"
r="1"
eR=10.0
se tornar="10"
r="8"
eR=80.0
se tornar="80"
E finalmente retornamos o resultado, depois que removemos os pontos à direita.
1203.
torna-se1203
5.
torna-se5
Definitivamente pode ser jogado por algumas centenas de bytes, mas estou feliz que esteja funcionando agora. Já demorou um pouco para entender cada um dos casos e o que estava sendo solicitado no desafio. E então foram necessárias muitas tentativas e erros, testes e retestes para chegar ao resultado acima. E enquanto escrevia essa explicação acima, eu era capaz de remover outros ± 50 bytes de código não utilizado.
fonte
501*2.0
a saída1000
(você deve produzir de1000
qualquer maneira , que eu interpreto como "imóvel", não de qualquer maneira ). Magnífico trabalho de qualquer maneira.