9
\$\begingroup\$

Write a program that converts a decimal to a mixed, simplified fraction.

Sample input:

5.2

Sample output:

5 + (1/5)

The code with the shortest length in bytes wins.

\$\endgroup\$
11
  • 6
    \$\begingroup\$ Easy: 1.2345 = 12345/10000. You give me the precision & I'll give you the fraction! \$\endgroup\$ Jan 2, 2014 at 21:52
  • \$\begingroup\$ Do you mean simplified fractions? \$\endgroup\$
    – hkk
    Jan 2, 2014 at 21:53
  • \$\begingroup\$ i meant mixed fractions \$\endgroup\$ Jan 2, 2014 at 21:58
  • 2
    \$\begingroup\$ 5.2 != 5+1/2... \$\endgroup\$
    – Kevin
    Jan 2, 2014 at 22:28
  • 1
    \$\begingroup\$ @Markasoftware: That won't necessarily work (the factor might not be prime) and it could take a long time. The best way (AFAIK) is to find the gcd of both (using the Euclidean algorithm) and divide through. \$\endgroup\$
    – Gelatin
    Jan 2, 2014 at 22:36

13 Answers 13

4
\$\begingroup\$

Ruby, 43

y=gets.to_r;puts"#{y.to_i} + (#{y-y.to_i})"

Pretty straightforward.

\$\endgroup\$
2
  • \$\begingroup\$ Interesting solution. I'm honestly surprised you can make such short program with correct output format. \$\endgroup\$
    – null
    Jan 3, 2014 at 17:47
  • \$\begingroup\$ Ruby has a lot of Lispy features and the Rational class is probably one of the lesser-known ones. However, if the input is a float you're liable to get something like "2 + (1499999999999999/5000000000000000)" \$\endgroup\$ Jan 4, 2014 at 4:01
2
\$\begingroup\$

python 3, 84

from fractions import*
a,b=input().split(".")
print("%s + (%s)"%(a,Fraction("."+b)))
\$\endgroup\$
5
  • \$\begingroup\$ Doesn't return the output in correct format. + should be returned (but otherwise, it's close to expected format). \$\endgroup\$
    – null
    Jan 3, 2014 at 7:03
  • \$\begingroup\$ @GlitchMr Edited the format. \$\endgroup\$
    – Wasi
    Jan 3, 2014 at 7:52
  • \$\begingroup\$ Also, there are parens. Dunno why, but the OP put them. \$\endgroup\$
    – null
    Jan 3, 2014 at 12:42
  • 1
    \$\begingroup\$ @GlitchMr Added those creepy parens. Now the code size raised to 84 :-( \$\endgroup\$
    – Wasi
    Jan 3, 2014 at 12:58
  • \$\begingroup\$ 81 bytes using f-string, code \$\endgroup\$
    – Saphereye
    Jul 18, 2023 at 10:43
2
\$\begingroup\$

GolfScript, 40

'.'/~'+'\.~.@,10\?.@{.@\%.}do;:d/\d/'/'@

Requires no line terminator in the input. Can probably be golfed further.

\$\endgroup\$
1
\$\begingroup\$

Golf-Basic 84, 32 characters

Executed from a TI-84 calculator

i`A:floor(A)→B:A-B→A:d`Bd`A►Frac
\$\endgroup\$
1
\$\begingroup\$

Mathematica 73

No cigar this time. Numerator, Denominator and Rationalize are big words.

f@x_:=(Row@{⌊#⌋,"+",Numerator@#~Mod~(d=Denominator@#)/d})&[Rationalize@x]

Example

f[23.872]

mixed

\$\endgroup\$
1
\$\begingroup\$

GTB, 28

`A:floor(A)→B:A-B→A~B~A►Frac
\$\endgroup\$
1
  • \$\begingroup\$ The source code for your compiler cannot be run since iX2Web is not available. The link in your site is bad as well. \$\endgroup\$
    – mbomb007
    Apr 13, 2015 at 20:58
1
\$\begingroup\$

Perl 6 (53 bytes)

Does the output in right, expected format. Would be way shorter if output in invalid format would be allowed. This gets a number, converts it to rational. nude method returns denominator and numerator (there are separate denominator and numerator methods, but they are crazily long.

[] is a reduce operator which takes operator between square brackets, and in this case, I use it to shorten the code (so I wouldn't have to specify both array elements, because they are already in correct order (but if they wouldn't, there are R operators (like R/, R%, Rdiv, and Rmod) that reverse the order of arguments for operator)). {} in double quotes puts the result of code in string (like #{} in Ruby).

my \ is declaration of sigilless variable. In this case it doesn't save characters, but it doesn't waste them either, so why not use it. I could have used my@, and it would use identical number of characters.

my \n=get.Rat.nude;say "{[div] n} + ({[%] n}/{n[1]})"

Sample output (just to show the correct format):

~ $ perl6 -e 'my \n=get.Rat.nude;say "{[div] n} + ({[%] n}/{n[1]})"'
42.42
42 + (21/50)

If negative number support is needed, this would work (2 bytes more).

~ $ perl6 -e 'my \n=get.Rat.nude;say "{[div] n} + ({[mod] n}/{n[1]})"'
-42.42
-42 + (-21/50)
\$\endgroup\$
1
\$\begingroup\$

R, several lines

How about the way they tought us at grammar school?

f=function(s){
  gcd=function(a,b)if(!b)a else gcd(b,a%%b)
  a=strsplit(s,'\\.')[[1]]
  p=10^nchar(a[2])
  x=strtoi(a[2])
  d=gcd(x,p);
  cat(a[1]," + (",x/d,"/",p/d,")",sep="");
}

Vaguely: works for positive decimals with finite decimal fraction.

> f("23.872")
23 + (109/125)

Input must be a string matching "[0-9]+\.[0-9]+" regular expression.

\$\endgroup\$
1
\$\begingroup\$

Haskell

Isn't pretty, but whatever

import Data.Ratio
main=let r '%'='/';r c=c in interact$(\(x,y)->show x++" + "++map r(show$approxRational y 1e-9)).properFraction.read
\$\endgroup\$
1
\$\begingroup\$

Vyxal, 20 19 bytes

I₌I-ƒJ`% + (%/%)`$%

Try it Online!

It's convoluted because of the handling of the output format

Explained (old)

:I₌₴-ƒ\/j`...`$%,
:I                # int(input)
  ₌₴-             # print(top, end=""), input - int(input) [gets the fractional part] 
     ƒ            # Turn the decimal into a simplified fraction
      \/j         # Join that on "/"
         `...`    # The string " + (%)" -> this will be used for formatting the output
              $%, # perform string formatting and output the fraction part
\$\endgroup\$
1
\$\begingroup\$

Pyth, 34 bytes

phAcQ\.s[" + ("/sHKisHJ*TlH\//JK\)

Not that proud of this but that output format was getting to my head

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Vyxal, 34 bitsv2, 4.25 bytes

1ḋ\+j

Does divmod with 1 and then joins on +. Outputs a+b/c.

Try it Online!

If the IO format was a bit looser

2 bytes

1ḋ

Does divmod with 1. Outputs ⟨ a | b/c ⟩

Try it Online!

\$\endgroup\$
0
0
\$\begingroup\$

Racket, 134 bytes

((λ(f[d(denominator f)][n(numerator f)])(printf"~a + (~a)"(quotient n d)(rationalize(/(modulo n d)d)(/ 1 d))))(inexact->exact(read)))

Try it online!


Explanation

Racket natively supports fractions. Fractions are referred to as "exact number" as the values of fraction aren't affected by IEEE floating-point conversion.

Racket also has support for floats, similar to what is present in other languages. These floats are called inexact numbers because their accuracy is limited to what can be stored in a certain number of bytes (IEEE standards).

Read more about Racket Numbers.

Since the user inputs a float with a decimal point, we need to convert the number into a fraction using inexact->exact. Once our input is converted, we can extract the denominator and the numerator of the fraction.

((λ (frac [den (denominator frac)] [num (numerator frac)])
   ...)
 (inexact->exact (read)))

After that, We create a format string that will printed with the following format parameters:

  1. The whole part of the fraction.
    1. Calculated by dividing the numerator num by the denominator den.
  2. A simplified version of the remaining fraction.
    1. Modulo the numerator num by the denominator den.
    2. Create a new fraction with the previous step as the numerator and the denominator as den.
    3. Rationalize the new fraction with a tolerance of \$\frac{1}{\text{den}}\$.
((λ (frac [den (denominator frac)] [num (numerator frac)])
   (printf "~a + (~a)"
           (quotient n d)
           (rationalize (/ (modulo n d) d)
                        (/ 1 d))))
 (inexact->exact (read)))

Have a great week further!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.