Arredondar para n Sig Figs


20

Desafio

Dado um número xe um número n, arredondar xpara nnúmeros significativos e gerar o resultado.

Figuras significativas

Os números significativos de um número são dígitos que carregam significado, contribuindo para sua resolução de medição. Isso inclui todos os números, exceto os zeros à esquerda.

Lembre-se de que zeros à esquerda após um ponto decimal ainda são números insignificantes .

Ao arredondar um dígito, você deve arredondar para zero se o dígito a seguir for maior ou igual a cinco.

Todos os zeros à direita após um ponto decimal são contados como significativos.

Entrada

O primeiro número será x, o número a ser arredondado. O segundo número será no número de números significativos para os quais você deve arredondar x.

xserá um número (seu código deve lidar com números inteiros e pontos flutuantes) entre -1.000.000.000 e 1.000.000.000 inclusive. nserá um número inteiro positivo entre 1 e 50, inclusive. nnunca será maior que o número de dígitos x.

A entrada nunca será 0ou qualquer forma de 0, por exemplo, 0.000ou 000.

Exemplos

Inputs: 2.6754, 2
Output: 2.7

Uma saída de 2.7000seria inválida porque os zeros à direita após o ponto decimal são contados como números significativos.


Inputs: 0.00034551, 4
Output: 0.0003455

Inputs: 50237.1238, 3
Output: 50200

Observe que isso não deve ter um ponto decimal.


Inputs: 2374905, 1
Output: 2000000

Inputs: 543.0489, 4
Output: 543.0

Inputs: 15, 1
Output: 20

Inputs: 520.3, 3
Output: 520

Se desejar, você pode produzir, em 520.vez disso, mas não 520.0.


Inputs: -53.87, 2
Output: -54

Inputs: 0.0999, 2
Output: 0.10

Regras

As funções e bibliotecas internas que permitem arredondar um número para nnúmeros significativos não são permitidas.

Ganhando

O código mais curto em bytes vence.


4
Pois Inputs: 520.3, 3, o ponto decimal na resposta não é 520.crucial?
Greg Martin

5
@GregMartin Eu acredito que ele é, como essa é a única coisa que o torna tem 3 ass figos vs. 2
Suever

3
@BetaDecay Não, não é. O ponto decimal seria necessário para isso.
Mbomb007

3
"200 é considerado como tendo apenas um número significativo" - chemistry.bd.psu.edu/jircitano/sigfigs.html
mbomb007 16/09/16

4
@DLosc É por isso que, se esse fosse o resultado, você realmente escreveria como 2.0 x 10^2, mostrando os 2 sigfigs.
mbomb007

Respostas:


3

Python 3, 83 bytes

(semelhante à resposta do PHP)

from math import *
def s(x,n):
 y=10**(ceil(log10(abs(x)))-n)
 return y*round(x/y)

Casos de teste:

tests = [(2.6754,2), (0.00034551, 4), (50237.1238, 3),
        (2374905, 1), (543.0489, 4), (15, 1), (520.3, 3), (-53.87, 2)]

print ([s(x,n) for x,n in tests])

Saída:

[2.7, 0.0003455, 50200, 2000000, 543.0, 20, 520, -54]

Além de ser um pouco mais longo, outra abordagem que considerei:

from math import *
def s(x,n):
 z=ceil(log10(abs(x)))
 return "%.*f"%(n-z,10**z*round(x/10**z,n))

... produz uma saída incorreta para a entrada de (15, 1):

['2.7', '0.0003455', '50200', '2000000', '543.0', '10', '520', '-54']

... devido à imprecisão do ponto flutuante na round()função. Parece-me provável que eu pudesse encontrar casos de teste que quebrariam o método "arredondar para zero casas decimais" também se eu parecesse bastante.

Assim, parece-me que minha solução provavelmente não é 100% correta para todos os casos e não seria, a menos que fosse computada em decimal. Portanto, esse problema pode afetar soluções em qualquer idioma que use a aritmética de FP.


Salve alguns bytes colocando o corpo de sna mesma linha e usando ponto e vírgula. def s(x,n):y=10**(ceil(log10(abs(x)))-n);return y*round(x/y)
Cyoce 19/09/16

Além disso, você pode remover o espaço import *para fazê-loimport*
Cyoce

sua resposta para mim não está correta porque as regras dizem: "Funções e bibliotecas integradas que permitem arredondar um número para n números significativos não são permitidos". E você usa a função round com n = 0
RosLuP

@RosLuP: A round()função arredonda para ncasas decimais, e não para nnúmeros significativos, por isso foi permitida para este evento de golfe.
Simon

5

PHP, 130 bytes

<?=number_format($r=round($i=$argv[1],($n=$argv[2])-ceil(log(abs($i),10))),($d=(1+floor(log(abs($r),10))-$n))<0?abs($d):0,".","");

PHP, 133 bytes trabalha com valores <1 para os números significativos

<?=number_format($r=round($i=$argv[1],($n=$argv[2])-floor(log(abs($i),10))-1),($d=(1+floor(log(abs($r),10))-$n))<0?abs($d):0,".","");

PHP, 56 bytes funciona, mas ignora zeros desnecessários

<?=round($i=$argv[1],$argv[2]-floor(log(abs($i),10))-1);

Alguém roubou ou excluiu a função round no PHP! Para tornar o desafio mais interessante. 127 bytes

<?=ceil($x=($i=$argv[1])*10**(($r=$argv[2])-($l=floor(log(abs($i),10))+1)))-$x<=0.5?ceil($x)*10**($l-$r):floor($x)*10**($l-$r);

Também pula os desagradáveis ​​Zeros. É uma versão em que não uso a função round nativa no PHP apenas por brincadeira. Pertence à versão de 56 bytes que eu preferiria
Jörg Hülsermann 19/09/16

Ok, se não usar rodada biblioteca ....
RosLuP

3

Lote, 660 652 bytes

@echo off
set m=%1.
set s=
if %m:~,1%==- set s=-&set m=%m:~1%
:m
if %m:~,1%==0 set m=%m:~1%&goto m
set d=%m:.=%
:d
if %d:~,1%==0 set d=%d:~1%&goto d
for /l %%i in (1,1,%2) do call set d=%%d%%0
call set r=%%d:~%2,1%%
call set d=%%d:~,%2%%
if %r% leq 4 goto r
set r=
:i
set/ai=1+%d:~-1%
set r=%i:~-1%%r%
set d=%d:~,-1%
if %i% leq 9 set d=%d%%r%&goto r
if not "%d%"=="" goto i
set d=1%r:~1%
set m=1%m%
set m=%m:1.0=.%
:r
if %m:~,2%==.0 set m=%m:.0=.%&set d=0%d%&goto r
set i=0
set p=.
:l
if %m:~,1%==. echo %s%%i%%p%%d%&exit/b
if %i%==0 set i=
if "%d%"=="" set d=0&set p=
set i=%i%%d:~,1%
set d=%d:~1%
set m=%m:~1%
goto l

Explicação: Inicia com o sufixo .a no parâmetro, caso ele ainda não tenha um, e apara o sinal (que é salvo) e os zeros à esquerda. A variável resultante mé salva para mais tarde porque nos dirá a magnitude desejada do resultado. Todos os .s são removidos, o que pode resultar em zeros à esquerda, e também são removidos. nzeros são sufixados para garantir que haja dígitos suficientes para arredondar e, em seguida, o nprimeiro e o terceiro ndígitos são extraídos. Se o ndígito th não for 4 ou menos, adicionaremos tediosamente 1à string. Se a cadeia estourar, aumentamos a magnitude prefixando a 1, mas se era originalmente menor do que o 0.1que fazemos, removendo o 1que acabamos de adicionar e também um0após o ponto decimal. Se a magnitude ainda for menor que 1, copiamos os zeros após o ponto decimal para o resultado; no entanto, se é 1ou mais, extraímos a parte inteira da resposta, adicionando zeros extras, se necessário, para atingir o ponto decimal (que é então excluído porque mostraria precisão incorreta). Finalmente, o sinal, a parte inteira, o ponto decimal e a parte decimal são concatenados.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.