Convert a fraction to a repeated decimal

17

Almost the polar opposite if this challenge, and I suspect it will be slightly easier.

Your task is to take two integers in the format a/b (Forming a rational number) then output the number in decimal exactly.

For example, if you were to input 1/3, it would output:

0.33333333333333333

And would keep on printing 3s until the end of time, with an optional leading 0. (You could also print one character per line if and only if your language does not allow printing on the same line.)

The behaviour for x/0 will be undefined. For a number that looks like it doesn't repeat (Like, say 5/4) it actually does repeat. Either of the following two forms would be acceptable for 5/4:

1.25000000000000000
1.24999999999999999

(The same with whole numbers, 1.9999999 or 2.000000)

The fraction may not be in its simplest form, and a or b may be negative (Note -a/b = -(a/b), -a/-b = a/b, a/-b = -a/b, and -.6249999 is invalid, but -0.6249999 is acceptable, but you still can use.

user34736

Posted 2015-05-04T12:26:52.690

Reputation:

Can we use Unix bc, or is that cheating? – David R Tribble – 2015-05-04T15:32:20.600

Before I keep golfing my answer: Can a and/or b be negative? – Dennis – 2015-05-04T16:18:35.110

@Dennis Yes, but either a or b (or both) can be negative) – None – 2015-05-04T16:34:18.247

@DavidRTribble I think that's a standard loophole, so no. – None – 2015-05-04T16:34:58.397

Does your latest edit say that leading zeroes are okay with positive numbers, but not negative ones? If so, what's the reason for that? – Geobits – 2015-05-04T16:56:42.227

@Geobits No it says the opposite (.0, 0.0, -0.0 are all OK, but -.0 isn't as it looks weird.) – None – 2015-05-04T19:07:18.047

Right, that's what I meant, said it backward. So the reason is "it looks weird"? Okay... – Geobits – 2015-05-04T19:12:26.737

Your last edit make some answer invalid (mine, above all). That should be avoided if possible. – edc65 – 2015-05-04T19:56:52.090

Answers

2

CJam, 38 37 bytes

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

How it works

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)

Dennis

Posted 2015-05-04T12:26:52.690

Reputation: 196 637

Since you use double division isn't this totally broken for big numbers? – orlp – 2015-05-05T01:18:51.903

@orlp: Totally. It's fixed now. – Dennis – 2015-05-05T13:10:41.713

6

C, 108 79

Edit Modified to work with negative numbers.

Input from stdin. Old K&R style.

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;}

edc65

Posted 2015-05-04T12:26:52.690

Reputation: 31 086

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}}

Simple implementation of manual integer division based on the computer's integer division.

Thanks to @blutorange for the help in golfing.

Edit: Fixed the solution to include negative numbers.

rorlork

Posted 2015-05-04T12:26:52.690

Reputation: 1 421

2By making use of some shortcuts in ruby, you can bring this down to 66 bytes: ->s{a,b=s.split(?/).map &:to_i;$><<a/b<<?.;loop{a=a%b*10;$><<a/b}} I just love this about ruby. – blutorange – 2015-05-04T15:31:14.093

Wow, I just learned many things, thank you! I didn't remember about ?/ to denote characters, nor did I know about $><< to print or the loop keyword. Thanks a lot!! – rorlork – 2015-05-04T15:36:14.847

1You're welcome, I didn't know about many of these tricks either until somebody pointed it out. $> is short for $stdout, and << is an operator. You can save one more byte in the second line by changing it to c*d<0&&$><<?-; a few bytes by combining the 3rd/4th line to $><<a/b<<?., and one more by removing the space after << in the last line. And here's an idea to bring it down to 91 bytes: ->s{a,b=s.scan(/\d+/).map &:to_i;1==s.count(?-)&&$><<?-;$><<a/b<<?.;loop{a=a%b*10;$><<a/b}} (ruby 2.2.0) – blutorange – 2015-05-04T18:45:33.697

The syntax for $><<a/b didn't work correctly, that's why I put the space there. The rest seems good, thank you very much! – rorlork – 2015-05-04T21:36:03.497

That's interesting, perhaps the ruby version you're using doesn't like it without spaces? It works fine for me and at ideone. Funny enough, it breaks the syntax highlighting of my code editor, though...

– blutorange – 2015-05-04T22:16:01.757

Oh, maybe it works and I just assumed it didn't because of the syntax highlighting in vim... edit: after trying it, it works, it was the syntax highlighting that led me to believe it wouldn't – rorlork – 2015-05-04T22:29:53.533

1

If you're still interested, there's also a rational literal (Rational(2,3) == 2/3r) since ruby 2.1 (that I learned about 10 mins ago) that can be used to shorten the second line: eval(s+?r)<0&&$><<?-

– blutorange – 2015-05-05T00:03:44.183

Thanks a lot! wow, ruby is really a complete language in many ways... And you are a true source of information! – rorlork – 2015-05-05T00:05:29.880

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){}}

The algorithm is straightforward; the tricky part was getting the printing to work. In the end, I had the computer sleep for a second between each step so it could print.

Expanded, runnable version

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");
    }
}

Ypnypn

Posted 2015-05-04T12:26:52.690

Reputation: 10 485

While the output does have a flushing problem, I was able to get it to show output by sleeping for 9ms which would shave two bytes. – None – 2015-05-04T15:37:17.277

@Snowman It probably depends on the hardware or OS; my computer won't work with less than 250ms or so. – Ypnypn – 2015-05-04T17:02:40.847

2

R, 103 137 109 103

Bit happier with this now. Using scan with a separator save a lot of bytes. May still have some room for improvement. Replaced <- with =. Haven't always had the best of luck with this, but it worked this time.

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

Test runs

> 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...

MickyT

Posted 2015-05-04T12:26:52.690

Reputation: 11 735

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="")

Pretty straightforward:

  • Input the numerator and denominator
  • Output the the quotient with 1 digit after the decimal point, then take off the last digit (e.g. -1/3 -> -0.)
  • Take absolute values*
  • Loop:
    • Numerator is remainder after dividing out denominator
    • Multiply numerator by 10
    • Output integer quotient as next digit

* (Though the calculation for a was moved inside the loop to save a few bytes.)

Edit: Fixed bug with negative fractions > -1.

DLosc

Posted 2015-05-04T12:26:52.690

Reputation: 21 213

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

edit:

Now outputs all characters on the same line, as asked.

edit2:

Now reads the fraction from commandline argument, as requested :)

dieter

Posted 2015-05-04T12:26:52.690

Reputation: 2 010

1

A few tips: 1) Using map instead of the list comprehension saves quite a bit; 2) don't need the parentheses around m*a in any of its locations, as *, %, and / are all the same precedence and left-associative; 3) the 0-or-dot logic on line 3 can be simplified to "0."[m==1], since you're just printing it anyway; 4) probably will save chars to merely set o=stdout.write and convert numeric arguments to string with backticks as needed.

– DLosc – 2015-05-04T21:41:34.477

1Also, the code doesn't appear to work with negatives: 1/-3 gives -1.666666666 instead of -0.333333333. – DLosc – 2015-05-04T21:42:51.130