Redondear a n Sig Figs

20

Desafío

Dado un número xy un número n, redondea el número xa ncifras significativas y genera el resultado.

Personajes importantes

Las cifras significativas de un número son dígitos que tienen un significado que contribuye a su resolución de medición. Esto incluye todos los números excepto los ceros a la izquierda.

Tenga en cuenta que los ceros a la izquierda después de un punto decimal siguen siendo cifras insignificantes .

Al redondear un dígito, debe redondear desde cero si el siguiente dígito es mayor o igual que cinco.

Todos los ceros finales después de un punto decimal se cuentan como significativos.

Entrada

El primer número será x, el número que se redondeará. El segundo número será n, el número de cifras significativas que debe redondear x.

xserá un número (su código debe manejar enteros y puntos flotantes) entre -1,000,000,000 y 1,000, 000,000 inclusive. nserá un número entero positivo entre 1 y 50 inclusive. nnunca será mayor que el número de dígitos en x.

La entrada nunca será 0o cualquier forma de 0, por ejemplo, 0.000o 000.

Ejemplos

Inputs: 2.6754, 2
Output: 2.7

Una salida de 2.7000sería inválida porque los ceros al final del punto decimal se cuentan como cifras significativas.


Inputs: 0.00034551, 4
Output: 0.0003455

Inputs: 50237.1238, 3
Output: 50200

Tenga en cuenta que esto no debe tener un punto decimal.


Inputs: 2374905, 1
Output: 2000000

Inputs: 543.0489, 4
Output: 543.0

Inputs: 15, 1
Output: 20

Inputs: 520.3, 3
Output: 520

Si lo desea, puede imprimir en su 520.lugar pero no 520.0.


Inputs: -53.87, 2
Output: -54

Inputs: 0.0999, 2
Output: 0.10

Reglas

Las funciones y bibliotecas integradas que le permiten redondear un número a ncifras significativas no están permitidas.

Victorioso

El código más corto en bytes gana.

Decaimiento Beta
fuente
44
por Inputs: 520.3, 3 , ¿no es 520.crucial el punto decimal en la respuesta ?
Greg Martin
55
@ GregMartin Creo que es así, ya que eso es lo único que hace que tenga 3 higos sig vs. 2
Suever
3
@BetaDecay No, no lo es. El punto decimal sería requerido para eso.
mbomb007
3
"200 se considera que tiene UNA sola cifra significativa" - chemistry.bd.psu.edu/jircitano/sigfigs.html
mbomb007
44
@DLosc Es por eso que si ese fuera el resultado, realmente lo escribirías como 2.0 x 10^2, mostrando las 2 sigfigs.
mbomb007

Respuestas:

3

Python 3, 83 bytes

(similar a la respuesta PHP)

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

Casos de prueba:

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

Salida:

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

Además de ser un poco más largo, otro enfoque que consideré:

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

... produce una salida incorrecta para la entrada de (15, 1):

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

... debido a la imprecisión de coma flotante en la round()función. Me parece probable que también pueda encontrar casos de prueba que rompan el método de "redondear a cero decimales" si busco lo suficiente.

Por lo tanto, me parece que mi solución probablemente no sea 100% correcta para todos los casos y no lo sería a menos que se calculara en decimal. Por lo tanto, este problema puede afectar las soluciones en cualquier lenguaje que use aritmética FP.

Simón
fuente
Guarde algunos bytes colocando el cuerpo de sen la misma línea, luego use punto y coma. def s(x,n):y=10**(ceil(log10(abs(x)))-n);return y*round(x/y)
Cyoce
Además, puede quitar el espacio import *para hacerloimport*
Cyoce
su respuesta para mí no está bien porque las reglas dicen: "Las funciones y bibliotecas integradas que le permiten redondear un número a n cifras significativas no están permitidas". Y utiliza la función redonda con n = 0
RosLuP
@RosLuP: la round()función se redondea a ndecimales, no a ncifras significativas, por lo que se permitió este evento de golf.
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 funciona con valores <1 para las cifras significativas

<?=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 pero omite los ceros innecesarios

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

¡Alguien ha robado o eliminado la función redonda en PHP! Para hacer el desafío más interesante. 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);
Jörg Hülsermann
fuente
También omite los ceros insensibles. Es una versión en la que no uso la función de ronda nativa en PHP solo por broma. Pertenece a la versión de 56 bytes que preferiría
Jörg Hülsermann
Ok si no usa la ronda de 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

Explicación: comienza con el sufijo .a en el parámetro en caso de que aún no tenga uno, luego recorta el signo (que se guarda) y los ceros a la izquierda. La variable resultante mse guarda para más adelante porque nos dirá la magnitud deseada del resultado. Cualquier .s se retiraron entonces, lo que podría dar lugar a nuevas ceros a la izquierda, por lo que se eliminan también. nlos ceros tienen el sufijo para garantizar que haya suficientes dígitos para redondear, luego se extraen los dígitos nth y first n. Si el ndígito th no es 4 o menos, entonces agregamos tediosamente 1a la cadena. Si la cadena se desborda, entonces aumentamos la magnitud con el prefijo a 1, pero si originalmente era menor que 0.1eso, eliminamos el1 eliminamos que acabamos de agregar y también un0después del punto decimal. Si la magnitud es aún menor que 1entonces, copiamos los ceros después del punto decimal al resultado, sin embargo, si es 1o más, extraemos la parte entera de la respuesta, agregando ceros adicionales si es necesario para llegar al punto decimal (que es entonces eliminado ya que mostraría una precisión incorrecta). Finalmente, el signo, la parte entera, el punto decimal y la parte decimal se concatenan.

Neil
fuente