Convertir una fracción a un decimal repetido


17

Casi el polo opuesto si este desafío, y sospecho que será un poco más fácil.

Su tarea es tomar dos enteros en el formato a/b(Formando un número racional) y luego generar el número en decimal exactamente.

Por ejemplo, si tuviera que ingresar 1/3, generaría:

0.33333333333333333

Y seguiría imprimiendo 3s hasta el final de los tiempos, con un 0 inicial opcional (también puede imprimir un carácter por línea si y solo si su idioma no permite imprimir en la misma línea).

El comportamiento para x/0será indefinido. Para un número que parece que no se repite (como, digamos 5/4), en realidad se repite. Cualquiera de las siguientes dos formas sería aceptable para 5/4:

1.25000000000000000
1.24999999999999999

(Lo mismo con números enteros, 1.9999999o 2.000000)

La fracción puede no estar en su forma más simple, y a, o bpuede ser negativo (Nota -a/b = -(a/b), -a/-b = a/b, a/-b = -a/b, y -.6249999no es válido, pero -0.6249999es aceptable, pero todavía se puede utilizar.


¿Podemos usar Unix bco es trampa?
David R Tribble

Antes de seguir jugando al golf, mi respuesta: ¿Puede ay / o bser negativo?
Dennis

@ Dennis Sí, pero uno ao bambos pueden ser negativos)

@DavidRTribble Creo que es una escapatoria estándar, así que no.

¿Su última edición dice que los ceros iniciales están bien con números positivos, pero no negativos? Si es así, ¿cuál es la razón de eso?
Geobits

Respuestas:


2

CJam, 38 37 bytes

l'/%:i2*~*0<'-*o:Dmd\zo'.{oA*Dmd\z1}g

Cómo funciona

l     e# Read line from STDIN.            STACK '17/-13'
'/%   e# Split at '/'.                    STACK ['17' '-13']
:i    e# Cast each element to int.        STACK [17 -13]
2*~   e# Duplicate and dump the array.    STACK 17 -13 17 -13
*     e# Multiply.                        STACK 17 -13 -221
0<    e# Compare with zero.               STACK 17 -13 1
'-*o  e# Print '-' that many times.       STACK 17 -13
:D    e# Save the topmost integer in D.   STACK 17 -13
md    e# Perform modular division.        STACK -1 4
\z    e# Swap and take absolute value.    STACK 4 1
o'.   e# Print and push '.'.              STACK 4 '.'
{     e# do:
  o   e#   Print.                         STACK 4
  A*  e#   Multiply by 10.                STACK 40
  Dmd e#   Divide modulo D.               STACK -3 1
  \z  e#   Swap and take absolute value.  STACK 1 3
  o   e#   Print.                         STACK 1
1}g   e# while(1)

Ya que usas doble división, ¿no está totalmente roto para números grandes?
orlp

@orlp: Totalmente. Ya está arreglado.
Dennis

6

C, 108 79

Editar modificado para trabajar con números negativos.

Entrada de stdin. Estilo antiguo de K&R.

main(a,b){char*s="-%d.";scanf("%d/%d",&a,&b);for(a*b<0?(a<0?a=-a:(b=-b)):++s;printf(s,a/b);s="%d")a=a%b*10;}

4

Ruby, 83 69 102 91 89 bytes

->s{a,b=s.scan(/\d+/).map &:to_i
eval(s+?r)<0&&$><<?-
$><<a/b<<?.
loop{a=a%b*10
$><<a/b}}

Implementación simple de la división de enteros manual basada en la división de enteros de la computadora.

Gracias a @blutorange por la ayuda en el golf.

Editar: se corrigió la solución para incluir números negativos.


2
Al hacer uso de algunos atajos en ruby, puedes reducir esto a 66 bytes: ->s{a,b=s.split(?/).map &:to_i;$><<a/b<<?.;loop{a=a%b*10;$><<a/b}}me encanta esto de ruby.
blutorange

Wow, acabo de aprender muchas cosas, ¡gracias! No recordaba sobre ?/denotar caracteres, ni sabía sobre $><<imprimir o la looppalabra clave. ¡¡Muchas gracias!!
rorlork

1
De nada, yo tampoco conocía muchos de estos trucos hasta que alguien lo señaló. $>es la abreviatura de $stdouty <<es un operador. Puede guardar un byte más en la segunda línea cambiándolo a c*d<0&&$><<?-; unos pocos bytes combinando la tercera / cuarta línea a $><<a/b<<?., y uno más eliminando el espacio después <<de la última línea. Y aquí hay una idea para ->s{a,b=s.scan(/\d+/).map &:to_i;1==s.count(?-)&&$><<?-;$><<a/b<<?.;loop{a=a%b*10;$><<a/b}}
reducirlo

La sintaxis para $><<a/bno funcionó correctamente, por eso puse el espacio allí. El resto parece bueno, muchas gracias!
rorlork

1
Si todavía está interesado, también hay un literal racional ( Rational(2,3) == 2/3r) desde ruby ​​2.1 (que aprendí hace unos 10 minutos) que se puede usar para acortar la segunda línea:eval(s+?r)<0&&$><<?-
blutorange

2

Java, 177 176 170

s->{try{int x=new Integer(s.split("/")[0]),y=new Integer(s.split("/")[1]),z=1;for(;;x=x%y*10,Thread.sleep(999))System.out.print(x/y+(z-->0?".":""));}catch(Exception e){}}

El algoritmo es sencillo; La parte difícil fue hacer que la impresión funcionara. Al final, hice que la computadora durmiera por un segundo entre cada paso para poder imprimir.

Versión ampliada y ejecutable

public class RepeatedDecimal {
    public static void main(String[] args) {
        java.util.function.Consumer<String> f = s -> {
                try {
                    int x = new Integer(s.split("/")[0]),
                        y = new Integer(s.split("/")[1]),
                        z = 1;
                    for (;; x = x % y * 10, Thread.sleep(999)) {
                        System.out.print(x / y + (z-- > 0 ? "." : ""));
                    }
                } catch (Exception e) { }
                };

        f.accept("5/7");
    }
}

Si bien la salida tiene un problema de descarga, pude hacer que muestre la salida durmiendo durante 9 ms, lo que reduciría dos bytes.

@Snowman Probablemente depende del hardware o del sistema operativo; mi computadora no funcionará con menos de 250 ms o menos.
Ypnypn

2

R, 103 137 109 103

Un poco más feliz con esto ahora. El uso de escaneo con un separador ahorra muchos bytes. Puede que aún tenga margen de mejora. Sustituido <-por =. No siempre he tenido la mejor de las suertes con esto, pero esta vez funcionó.

cat(if(prod(i=scan(sep='/'))<0)'-',(n=(i=abs(i))[1])%/%(d=i[2]),'.',sep='');repeat cat((n=n%%d*10)%/%d)

Pruebas de funcionamiento

> cat(if(prod(i=scan(sep='/'))<0)'-',(n=(i=abs(i))[1])%/%(d=i[2]),'.',sep='');repeat cat((n=n%%d*10)%/%d)
1: -1/3
3: 
Read 2 items
-0.33333333333333333333...
> cat(if(prod(i=scan(sep='/'))<0)'-',(n=(i=abs(i))[1])%/%(d=i[2]),'.',sep='');repeat cat((n=n%%d*10)%/%d)
1: -5/-4
3: 
Read 2 items
1.250000000000000000000...

1

Python 3, 107 115 bytes

a,b=map(int,input().split("/"))
print(("%.1f"%(a/b))[:-1],end="")
b=abs(b)
while 1:a=abs(a)%b*10;print(a//b,end="")

Muy claro:

  • Ingrese el numerador y el denominador
  • Saca el cociente con 1 dígito después del punto decimal, luego quita el último dígito (por ejemplo, -1/3-> -0.)
  • Tomar valores absolutos *
  • Lazo:
    • El numerador es el resto después de dividir el denominador.
    • Multiplicar el numerador por 10
    • Salida del cociente entero como siguiente dígito

* (Aunque el cálculo para ase movió dentro del bucle para guardar algunos bytes).

Editar: Corregido error con fracciones negativas> -1.


0

Python 2.7, 209 bytes

from sys import*;m,o=1,lambda x:stdout.write(str(x));a,b=[int(x)for x in argv[1].split('/')]
o(str(a*b)[0]);a,b=abs(a),abs(b);o('0'*(b>a))
while 1:
 while not((m*a)/b):o('0.'[m==1]);m*=10
 o((m*a)/b);a=(m*a)%b

editar:

Ahora genera todos los caracteres en la misma línea, como se le solicitó.

edit2:

Ahora lee la fracción del argumento de la línea de comandos, según lo solicitado :)


1
Algunos consejos: 1) Usar map lugar de la comprensión de la lista ahorra bastante; 2) no necesitan los paréntesis alrededor m*aen cualquiera de sus ubicaciones, como *, %y /son todos la misma prioridad y asociativo por la izquierda; 3) la lógica de 0 o punto en la línea 3 se puede simplificar "0."[m==1], ya que de todos modos solo la está imprimiendo; 4) probablemente guardará caracteres para simplemente establecer o=stdout.writey convertir argumentos numéricos en cadenas con comillas invertidas según sea necesario.
DLosc

1
Además, el código no parece funcionar con negativos: 1/-3da en -1.666666666lugar de -0.333333333.
DLosc
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.