Convert decimal number to rational: Difference between revisions

New post.
m (Reverted edits by Thundergnat (talk) to last revision by Chunes)
(New post.)
 
(39 intermediate revisions by 22 users not shown)
Line 20:
* 0.75 → 3 / 4
<br><br>
 
=={{header|11l}}==
{{trans|Nim}}
 
<syntaxhighlight lang="11l">T Rational
Int numerator
Int denominator
 
F (numerator, denominator)
.numerator = numerator
.denominator = denominator
 
F String()
I .denominator == 1
R String(.numerator)
E
R .numerator‘//’(.denominator)
 
F rationalize(x, tol = 1e-12)
V xx = x
V flagNeg = xx < 0.0
I flagNeg
xx = -xx
I xx < 1e-10
R Rational(0, 1)
I abs(xx - round(xx)) < tol
R Rational(Int(xx), 1)
V a = 0
V b = 1
V c = Int(ceil(xx))
V d = 1
V aux1 = 7FFF'FFFF I/ 2
L c < aux1 & d < aux1
V aux2 = (Float(a) + Float(c)) / (Float(b) + Float(d))
I abs(xx - aux2) < tol
L.break
I xx > aux2
a += c
b += d
E
c += a
d += b
V g = gcd(a + c, b + d)
I flagNeg
R Rational(-(a + c) I/ g, (b + d) I/ g)
E
R Rational((a + c) I/ g, (b + d) I/ g)
 
print(rationalize(0.9054054054))
print(rationalize(0.9054054054, 0.0001))
print(rationalize(0.5185185185))
print(rationalize(0.5185185185, 0.0001))
print(rationalize(0.75))
print(rationalize(0.1428571428, 0.001))
print(rationalize(35.000))
print(rationalize(35.001))
print(rationalize(0.9))
print(rationalize(0.99))
print(rationalize(0.909))
print(rationalize(0.909, 0.001))</syntaxhighlight>
 
{{out}}
<pre>
1910136854//2109703391
67//74
983902907//1897527035
14//27
3//4
1//7
35
35001//1000
9//10
99//100
909//1000
10//11
</pre>
 
=={{header|Ada}}==
Specification of a procedure Real_To_Rational, which is searching for the best approximation of a real number. The procedure is generic. I.e., you can instantiate it by your favorite "Real" type (Float, Long_Float, ...).
 
<langsyntaxhighlight Adalang="ada">generic
type Real is digits <>;
procedure Real_To_Rational(R: Real;
Bound: Positive;
Nominator: out Integer;
Denominator: out Positive);</langsyntaxhighlight>
 
The implementation (just brute-force search for the best approximation with Denominator less or equal Bound):
 
<langsyntaxhighlight Adalang="ada">procedure Real_To_Rational (R: Real;
Bound: Positive;
Nominator: out Integer;
Line 61 ⟶ 137:
Nominator := Integer(Real'Rounding(Real(Denominator) * R));
 
end Real_To_Rational;</langsyntaxhighlight>
 
The main program, called "Convert_Decimal_To_Rational", reads reals from the standard input until 0.0. It outputs progressively better rational approximations of the reals, where "progressively better" means a larger Bound for the Denominator:
 
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO; With Real_To_Rational;
 
procedure Convert_Decimal_To_Rational is
Line 90 ⟶ 166:
end loop;
end Convert_Decimal_To_Rational;
</syntaxhighlight>
</lang>
 
Finally, the output (reading the input from a file):
Line 105 ⟶ 181:
0.000000000
</pre>
 
=={{header|AppleScript}}==
<syntaxhighlight lang="applescript">--------- RATIONAL APPROXIMATION TO DECIMAL NUMBER -------
<lang applescript>on run
script ratioString
-- Using a tolerance epsilon of 1/10000
on |λ|(x)
showRatio(approxRatio(1.0E-4, x))
end |λ|
end script
map(ratioString, ¬
{0.9054054, 0.518518, 0.75})
--> {"67/74", "14/27", "3/4"}
end run
 
 
-- approxRatio :: Real -> Real -> Ratio
on approxRatio(epsilon, n)
if {real, integer} contains (class of epsilon) and 0 < epsilon then
-- Given
set e to epsilon
else
-- Default
set e to 1 / 10000
end if
Line 162 ⟶ 227:
 
 
-- GENERIC FUNCTIONS ------------------------- TEST -------------------------
on run
script ratioString
-- Using a tolerance epsilon of 1/10000
on |λ|(x)
(x as string) & " -> " & showRatio(approxRatio(1.0E-4, x))
end |λ|
end script
unlines(map(ratioString, ¬
{0.9054054, 0.518518, 0.75}))
-- 0.9054054 -> 67/74
-- 0.518518 -> 14/27
-- 0.75 -> 3/4
end run
 
 
-------------------- GENERIC FUNCTIONS -------------------
 
-- abs :: Num -> Num
Line 185 ⟶ 268:
end if
end mReturn
 
 
-- map :: (a -> b) -> [a] -> [b]
Line 196 ⟶ 280:
return lst
end tell
end map</lang>
 
 
-- unlines :: [String] -> String
on unlines(xs)
-- A single string formed by the intercalation
-- of a list of strings with the newline character.
set {dlm, my text item delimiters} to ¬
{my text item delimiters, linefeed}
set s to xs as text
set my text item delimiters to dlm
s
end unlines</syntaxhighlight>
{{Out}}
<pre>{"0.9054054 -> 67/74", "14/27", "3/4"}</pre>
0.518518 -> 14/27
0.75 -> 3/4</pre>
 
=={{header|AutoHotkey}}==
 
<langsyntaxhighlight AutoHotkeylang="autohotkey"> Array := []
inputbox, string, Enter Number
stringsplit, string, string, .
Line 288 ⟶ 386:
MsgBox % String . " -> " . String1 . " " . Ans
reload
</syntaxhighlight>
</lang>
<pre>
0.9054054 -> 67/74
Line 296 ⟶ 394:
 
=={{header|Bracmat}}==
<langsyntaxhighlight lang="bracmat">( ( exact
= integerPart decimalPart z
. @(!arg:?integerPart "." ?decimalPart)
Line 367 ⟶ 465:
)
)
);</langsyntaxhighlight>
Output:
<pre>0.9054054054 = 4527027027/5000000000 (approx. 67/74)
Line 385 ⟶ 483:
 
=={{header|C}}==
Since the intention of the task giver is entirely unclear, here's another version of best rational approximation of a floating point number. It's somewhat more rigorous than the Perl version below, but is still not quite complete.<langsyntaxhighlight Clang="c">#include <stdio.h>
#include <stdlib.h>
#include <math.h>
Line 457 ⟶ 555:
 
return 0;
}</langsyntaxhighlight>Output:<syntaxhighlight lang="text">f = 0.14285714285714
denom <= 1: 0/1
denom <= 16: 1/7
Line 473 ⟶ 571:
denom <= 65536: 104348/33215
denom <= 1048576: 3126535/995207
denom <= 16777216: 47627751/15160384</langsyntaxhighlight>
 
=={{header|C sharp|C#}}==
 
{{trans|C}}
<langsyntaxhighlight lang="csharp">using System;
using System.Text;
 
Line 553 ⟶ 651:
}
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 565 ⟶ 663:
2.71828182845905 → 49171 / 18089</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="c++">
#include <cmath>
#include <cstdint>
#include <iostream>
#include <limits>
#include <numeric>
#include <vector>
 
class Rational {
public:
Rational(const int64_t& numer, const uint64_t& denom) : numerator(numer), denominator(denom) { }
 
Rational negate() {
return Rational(-numerator, denominator);
}
 
std::string to_string() {
return std::to_string(numerator) + " / " + std::to_string(denominator);
}
 
private:
int64_t numerator;
uint64_t denominator;
};
/**
* Return a Rational such that its numerator / denominator = 'decimal', correct to dp decimal places,
* where dp is minimum of 'decimal_places' and the number of decimal places in 'decimal'.
*/
Rational decimal_to_rational(double decimal, const uint32_t& decimal_places) {
const double epsilon = 1.0 / std::pow(10, decimal_places);
 
const bool negative = ( decimal < 0.0 );
if ( negative ) {
decimal = -decimal;
}
 
if ( decimal < std::numeric_limits<double>::min() ) {
return Rational(0, 1);
}
 
if ( std::abs( decimal - std::round(decimal) ) < epsilon ) {
return Rational(std::round(decimal), 1);
}
 
uint64_t a = 0;
uint64_t b = 1;
uint64_t c = static_cast<uint64_t>(std::ceil(decimal));
uint64_t d = 1;
const uint64_t auxiliary_1 = std::numeric_limits<uint64_t>::max() / 2;
 
while ( c < auxiliary_1 && d < auxiliary_1 ) {
const double auxiliary_2 = static_cast<double>( a + c ) / ( b + d );
 
if ( std::abs(decimal - auxiliary_2) < epsilon ) {
break;
}
 
if ( decimal > auxiliary_2 ) {
a = a + c;
b = b + d;
} else {
c = a + c;
d = b + d;
}
}
 
const uint64_t divisor = std::gcd(( a + c ), ( b + d ));
Rational result(( a + c ) / divisor, ( b + d ) / divisor);
return ( negative ) ? result.negate() : result;
}
 
int main() {
for ( const double& decimal : { 3.1415926535, 0.518518, -0.75, 0.518518518518, -0.9054054054054, -0.0, 2.0 } ) {
std::cout << decimal_to_rational(decimal, 9).to_string() << std::endl;
}
}
</syntaxhighlight>
{{ out }}
<pre>
104348 / 33215
36975 / 71309
-3 / 4
14 / 27
-67 / 74
0 / 1
2 / 1
</pre>
 
=={{header|Clojure}}==
Line 604 ⟶ 789:
=={{header|D}}==
{{trans|Ada}}
<langsyntaxhighlight lang="d">import std.stdio, std.math, std.string, std.typecons;
 
alias Fraction = Tuple!(int,"nominator", uint,"denominator");
Line 643 ⟶ 828:
writeln();
}
}</langsyntaxhighlight>
{{out}}
<pre>0.750000000 1/1 3/4 3/4 3/4 3/4 3/4
Line 653 ⟶ 838:
-0.423310825 0/1 -3/7 -11/26 -69/163 -1253/2960 -10093/23843
31.415926536 31/1 157/5 377/12 3550/113 208696/6643 2918194/92889</pre>
=={{header|Delphi}}==
{{libheader| Velthuis.BigRationals}}
{{libheader| Velthuis.BigDecimals}}
Thanks Rudy Velthuis for Velthuis.BigRationals and Velthuis.BigDecimals library[https://github.com/rvelthuis/DelphiBigNumbers].
{{Trans|Go}}
<syntaxhighlight lang="delphi">
program Convert_decimal_number_to_rational;
 
{$APPTYPE CONSOLE}
 
uses
Velthuis.BigRationals,
Velthuis.BigDecimals;
 
const
Tests: TArray<string> = ['0.9054054', '0.518518', '0.75'];
 
var
Rational: BigRational;
Decimal: BigDecimal;
 
begin
for var test in Tests do
begin
Decimal := test;
Rational := Decimal;
Writeln(test, ' = ', Rational.ToString);
end;
Readln;
end.</syntaxhighlight>
=={{header|EchoLisp}}==
The '''rationalize''' function uses a Stern-Brocot tree [http://en.wikipedia.org/wiki/Stern%E2%80%93Brocot_tree] to find the best rational approximation of an inexact (floating point) number, for a given precision. The '''inexact->exact''' function returns a rational approximation for the default precision 0.0001 .
<langsyntaxhighlight lang="scheme">
(exact->inexact 67/74)
→ 0.9054054054054054
Line 684 ⟶ 898:
"precision:10^-13 PI = 5419351/1725033"
"precision:10^-14 PI = 58466453/18610450"
</syntaxhighlight>
</lang>
 
=={{header|Factor}}==
<langsyntaxhighlight lang="factor">USING: kernel math.floating-point prettyprint ;
 
0.9054054 0.518518 0.75 [ double>ratio . ] tri@</langsyntaxhighlight>
{{out}}
<pre>
Line 697 ⟶ 911:
</pre>
 
=={{header|FōrmulæFermat}}==
Fermat does this automatically.
{{out}}
<pre>
>3.14
 
157 / 50; or 3.1400000000000000000000000000000000000000
In [http://wiki.formulae.org/Convert_decimal_number_to_rational this] page you can see the solution of this task.
 
>10.00000
Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text ([http://wiki.formulae.org/Editing_F%C5%8Drmul%C3%A6_expressions more info]). Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation &mdash;i.e. XML, JSON&mdash; they are intended for transportation effects more than visualization and edition.
 
10
The option to show Fōrmulæ programs and their results is showing images. Unfortunately images cannot be uploaded in Rosetta Code.
 
>77.7777
 
777777 / 10000; or 77.7777000000000000000000000000000000000000
 
>-5.5
 
-11 / 2; or -5.5000000000000000000000000000000000000000
</pre>
 
=={{header|Forth}}==
<syntaxhighlight lang="forth">
<lang Forth>
\ Brute force search, optimized to search only within integer bounds surrounding target
\ Forth 200x compliant
Line 742 ⟶ 969:
2.71828e 1000 RealToRational swap . . 1264 465
0.9054054e 100 RealToRational swap . . 67 74
</syntaxhighlight>
</lang>
 
 
=={{header|Fortran}}==
Line 750 ⟶ 976:
Rather than engage in fancy schemes, here are two "brute force" methods. The first simply multiplies the value by a large power of ten, then casts out common factors in P/Q = x*1000000000/100000000. But if the best value for Q involves factors other than two and five, this won't work well. The second method is to jiggle either P or Q upwards depending on whether P/Q is smaller or larger than X, reporting improvements as it goes. Once beyond small numbers there are many small improvements to be found, so only those much better than the previous best are reported. Loosely speaking, the number of digits correct in good values of P/Q should be the sum of the number of digits in P and Q, and more still for happy fits, but a factor of eight suffices to suppress the rabble. Thus for Pi, the famous 22/7 and 355/113 appear as desired. Later pairs use lots more digits without a surprise hit, except for the short decimal sequence which comes out as 314159/100000 that reconstitutes the given decimal fraction exactly. Which is not a good approximation for Pi, and its pairs diverge from those of the more accurate value. In other words, one must assess the precision of the given value and not be distracted by the spurious precision offered by the larger P/Q pairs, so for 3·14159 with six digits, there is little point in going further than 355/113 - with their six digits. Contrariwise, if a P/Q with few digits matches many more digits of the given number, then a source rational number can be suspected. But if given just a few digits, such as 0·518 (or 0·519, when rounded), 13/25 could be just as likely a source number as 14/27 which is further away.
 
The source uses the MODULE facility of F90 merely to avoid the annoyance of having to declare the type of integer function GCD. The T ("tab") format code is employed to facilitate the alignment of output, given that P/Q is presented with I0 format so that there are no spaces (as in " 22/ 7" for example), the latter being standard in F90 but an extension in earlier Fortrans. <langsyntaxhighlight Fortranlang="fortran"> MODULE PQ !Plays with some integer arithmetic.
INTEGER MSG !Output unit number.
CONTAINS !One good routine.
Line 846 ⟶ 1,072:
CALL RATIONALISE(0.518518D0,"Two repeats, truncated.")
CALL RATIONALISE(0.518519D0,"Two repeats, rounded.")
END</langsyntaxhighlight>
 
Some examples. Each rational value is followed by X - P/Q. Notice that 0·(518) repeating, presented as 0·518518, is ''not'' correctly rounded.
Line 978 ⟶ 1,204:
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight FreeBasiclang="freebasic">'' Written in FreeBASIC
'' (no error checking, limited to 64-bit signed math)
type number as longint
Line 1,039 ⟶ 1,265:
if n = "" then exit do
print n & ":", parserational(n)
loop</langsyntaxhighlight>
 
=={{header|Frink}}==
<syntaxhighlight lang="frink">println[toRational[0.9054054]]
println[toRational[0.518518]]
println[toRational[0.75]]</syntaxhighlight>
{{out}}
<pre>
4527027/5000000 (exactly 0.9054054)
259259/500000 (exactly 0.518518)
3/4 (exactly 0.75)
</pre>
 
 
=={{header|Fōrmulæ}}==
 
{{FormulaeEntry|page=https://formulae.org/?script=examples/Convert_decimal_number_to_rational}}
 
'''Solution'''
 
=== Without repeating digits===
 
The Fōrmulæ '''Rationalize''' expression converts from decimal numberts to rational in lower terms.
 
[[File:Fōrmulæ - Convert decimal number to rational 01.png]]
 
[[File:Fōrmulæ - Convert decimal number to rational 02.png]]
 
 
[[File:Fōrmulæ - Convert decimal number to rational 03.png]]
 
[[File:Fōrmulæ - Convert decimal number to rational 04.png]]
 
=== With repeating digits ===
 
Fōrmulæ '''Rationalize''' expression can convert from decimal numbers with infinite number of repeating digits. The second arguments specifies the number of repeating digits.
 
[[File:Fōrmulæ - Convert decimal number to rational 05.png]]
 
[[File:Fōrmulæ - Convert decimal number to rational 06.png]]
 
 
In the following example, a conversion of the resulting rational back to decimal is provided in order to prove that it was correct:
 
[[File:Fōrmulæ - Convert decimal number to rational 07.png]]
 
[[File:Fōrmulæ - Convert decimal number to rational 08.png]]
 
[[File:Fōrmulæ - Convert decimal number to rational 09.png]]
 
[[File:Fōrmulæ - Convert decimal number to rational 10.png]]
 
 
[https://en.wikipedia.org/wiki/0.999... 0.999... is actually 1]:
 
[[File:Fōrmulæ - Convert decimal number to rational 11.png]]
 
[[File:Fōrmulæ - Convert decimal number to rational 12.png]]
 
=== Programatically ===
 
Even when rationalization expressions are intrinsic in Fōrmulæ, we can write explicit functions:
 
[[File:Fōrmulæ - Convert decimal number to rational 13.png]]
 
[[File:Fōrmulæ - Convert decimal number to rational 14.png]]
 
[[File:Fōrmulæ - Convert decimal number to rational 15.png]]
 
 
[[File:Fōrmulæ - Convert decimal number to rational 16.png]]
 
[[File:Fōrmulæ - Convert decimal number to rational 17.png]]
 
[[File:Fōrmulæ - Convert decimal number to rational 18.png]]
 
[[File:Fōrmulæ - Convert decimal number to rational 19.png]]
 
[[File:Fōrmulæ - Convert decimal number to rational 20.png]]
 
=={{header|Go}}==
Go has no native decimal representation so strings are used as input here. The program parses it into a Go rational number, which automatically reduces.
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,058 ⟶ 1,362:
}
}
}</langsyntaxhighlight>
Output:
<pre>
Line 1,071 ⟶ 1,375:
 
'''Test:'''
<langsyntaxhighlight lang="groovy">Number.metaClass.mixin RationalCategory
 
[
Line 1,077 ⟶ 1,381:
].each{
printf "%30.27f %s\n", it, it as Rational
}</langsyntaxhighlight>
 
'''Output:'''
Line 1,093 ⟶ 1,397:
 
The first map finds the simplest fractions within a given radius, because the floating-point representation is not exact. The second line shows that the numbers could be parsed into fractions at compile time if they are given the right type. The last converts the string representation of the given values directly to fractions.
<langsyntaxhighlight lang="haskell">Prelude> map (\d -> Ratio.approxRational d 0.0001) [0.9054054, 0.518518, 0.75]
[67 % 74,14 % 27,3 % 4]
Prelude> [0.9054054, 0.518518, 0.75] :: [Rational]
[4527027 % 5000000,259259 % 500000,3 % 4]
Prelude> map (fst . head . Numeric.readFloat) ["0.9054054", "0.518518", "0.75"] :: [Rational]
[4527027 % 5000000,259259 % 500000,3 % 4]</langsyntaxhighlight>
 
=={{header|J}}==
J's <code>x:</code> built-in will find a rational number which "best matches" a floating point number.
 
<langsyntaxhighlight lang="j"> x: 0.9054054 0.518518 0.75 NB. find "exact" rational representation
127424481939351r140737488355328 866492568306r1671094481399 3r4</langsyntaxhighlight>
 
These numbers are ratios where the integer on the left of the <code>r</code> is the numerator and the integer on the right of the <code>r</code> is the denominator. (Note that this use is in analogy with floating point notion, though it is true that hexadecimal notation and some languages' typed numeric notations use letters within numbers. Using letters rather than other characters makes lexical analysis simpler to remember - both letters and numbers are almost always "word forming characters".)
 
Note that the concept of "best" has to do with the expected precision of the argument:
<langsyntaxhighlight lang="j"> x: 0.9 0.5
9r10 1r2
x: 0.9054 0.5185
Line 1,120 ⟶ 1,424:
67r74 14r27
x: 0.9054054054054054 0.5185185185185185
67r74 14r27</langsyntaxhighlight>
 
Note that J allows us to specify an epsilon, for the purpose of recognizing a best fit, but the allowed values must be rather small. In J version 6, the value 5e_11 was nearly the largest epsilon allowed:
 
<langsyntaxhighlight lang="j"> x:(!. 5e_11) 0.9054054054 0.5185185185
67r74 14r27</langsyntaxhighlight>
 
(Note that epsilon will be scaled by magnitude of the largest number involved in a comparison when testing floating point representations of numbers for "equality". Note also that this J implementation uses 64 bit ieee floating point numbers.)
Line 1,131 ⟶ 1,435:
Here are some other alternatives for dealing with decimals and fractions:
 
<langsyntaxhighlight lang="j"> 0j10": x:inv x: 0.9054054 0.518518 0.75 NB. invertible (shown to 10 decimal places)
0.9054054000 0.5185180000 0.7500000000
0j10": x:inv 67r74 42r81 3r4 NB. decimal representation (shown to 10 decimal places)
0.9054054054 0.5185185185 0.7500000000
x: x:inv 67r74 42r81 3r4 NB. invertible
67r74 14r27 3r4</langsyntaxhighlight>
 
=={{header|Java}}==
<syntaxhighlight lang="java">
<lang java>import org.apache.commons.math3.fraction.BigFraction;
double fractionToDecimal(String string) {
int indexOf = string.indexOf(' ');
int integer = 0;
int numerator, denominator;
if (indexOf != -1) {
integer = Integer.parseInt(string.substring(0, indexOf));
string = string.substring(indexOf + 1);
}
indexOf = string.indexOf('/');
numerator = Integer.parseInt(string.substring(0, indexOf));
denominator = Integer.parseInt(string.substring(indexOf + 1));
return integer + ((double) numerator / denominator);
}
 
String decimalToFraction(double value) {
String string = String.valueOf(value);
string = string.substring(string.indexOf('.') + 1);
int numerator = Integer.parseInt(string);
int denominator = (int) Math.pow(10, string.length());
int gcf = gcf(numerator, denominator);
if (gcf != 0) {
numerator /= gcf;
denominator /= gcf;
}
int integer = (int) value;
if (integer != 0)
return "%d %d/%d".formatted(integer, numerator, denominator);
return "%d/%d".formatted(numerator, denominator);
}
 
int gcf(int valueA, int valueB) {
if (valueB == 0) return valueA;
else return gcf(valueB, valueA % valueB);
}
</syntaxhighlight>
<pre>
67/74 = 0.9054054054054054
14/27 = 0.5185185185185185
0.9054054 = 4527027/5000000
0.518518 = 259259/500000
</pre>
<br />
<syntaxhighlight lang="java">import org.apache.commons.math3.fraction.BigFraction;
 
public class Test {
Line 1,150 ⟶ 1,497:
System.out.printf("%-12s : %s%n", d, new BigFraction(d, 0.00000002D, 10000));
}
}</langsyntaxhighlight>
<pre>0.75 : 3 / 4
0.518518 : 37031 / 71417
Line 1,162 ⟶ 1,509:
=={{header|JavaScript}}==
Deriving an approximation within a specified tolerance:
<langsyntaxhighlight JavaScriptlang="javascript">(() => {
'"use strict'";
 
// ---------------- APPROXIMATE RATIO ----------------
 
// approxRatio :: Real -> Real -> Ratio
const approxRatio = epsilon =>
n => {
const
c = gcdApprox(
0 < epsilon
? epsilon
: (1 / 10000)
)(1, n);
 
return Ratio(
Math.floor(n / c),
Math.floor(1 / c)
);
};
 
 
// gcdApprox :: Real -> (Real, Real) -> Real
const gcdApprox = epsilon =>
(x, y) => {
const _gcd = (a, b) =>
b < epsilon
? a
: _gcd(b, a % b);
 
return _gcd(Math.abs(x), Math.abs(y));
};
 
 
// ---------------------- TEST -----------------------
// main :: IO ()
const main = () =>
showJSON(// Using a tolerance of 1/10000
[0.9054054, 0.518518, 0.75]
map( // Using a tolerance epsilon of 1/10000
.map(
n => showRatio(approxRatio(0.0001)(n)),
[0.9054054, 0.518518, 0.75]compose(
showRatio,
approxRatio(0.0001)
)
);
.join("\n");
 
// Epsilon -> Real -> Ratio
 
// ---------------- GENERIC FUNCTIONS ----------------
// approxRatio :: Real -> Real -> Ratio
 
const approxRatio = eps => n => {
// compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
const
const gcdecompose = (e, x, y...fs) => {
// A function defined by the right-to-left
const _gcd = (a, b) => (b < e ? a : _gcd(b, a % b));
// composition of all the functions in fs.
return _gcd(Math.abs(x), Math.abs(y));
},fs.reduce(
c(f, = gcde(Boolean(epsg) ?=> epsx :=> f(1 / 10000g(x)), 1, n);
return Ratio( x => x
Math.floor(n / c), // numerator
Math.floor(1 / c) // denominator
);
};
 
// GENERIC FUNCTIONS ----------------------------------
 
// Ratio :: Int -> Int -> Ratio
const Ratio = (n, d) => ({
type: '"Ratio'",
'n': n, // numerator
'd': d // denominator
});
 
// map :: (a -> b) -> [a] -> [b]
const map = (f, xs) => xs.map(f);
 
// showJSON :: a -> String
const showJSON = x => JSON.stringify(x, null, 2);
 
// showRatio :: Ratio -> String
const showRatio = nd =>
`${nd.n.toString() + '}/' + ${nd.d.toString()}`;
 
 
// MAIN ---
return main();
})();</langsyntaxhighlight>
{{Out}}
<pre>[67/74
14/27
"67/74",
3/4</pre>
"14/27",
 
"3/4"
=={{header|jq}}==
]</pre>
'''Works with [[#jq|jq]]''' (*)
 
'''Works with gojq, the Go implementation of jq'''
 
The following definition of `number_to_r` can be used for JSON numbers in general, as illustrated by the examples.
 
This entry assumes the availability
of two functions (`r/2` and `power/1`) as defined in
the "rational" module
at [[Arithmetic/Rational#jq]], which also provides a definition
for `rpp/0`, a pretty-printer used in the examples.
 
(*) With the caveat that the C implementation of jq does not support unlimited-precision integer arithmetic.
 
<syntaxhighlight lang="jq"># include "rational"; # a reminder that r/2 and power/1 are required
 
# Input: any JSON number, not only a decimal
# Output: a rational, constructed using r/2
# Requires power/1 (to take advantage of gojq's support for integer arithmetic)
# and r/2 (for rational number constructor)
def number_to_r:
 
# input: a decimal string
# $in - either null or the original input
# $e - the integer exponent of the original number, or 0
def dtor($in; $e):
index(".") as $ix
| if $in and ($ix == null) then $in
else (if $ix then sub("[.]"; "") else . end | tonumber) as $n
| (if $ix then ((length - ($ix+1)) - $e) else - $e end) as $p
| if $p >= 0
then r( $n; 10|power($p))
else r( $n * (10|power(-$p)); 1)
end
end;
. as $in
| tostring
| if (test("[Ee]")|not) then dtor($in; 0)
else capture("^(?<s>[^eE]*)[Ee](?<e>.*$)")
| (.e | if length > 0 then tonumber else 0 end) as $e
| .s | dtor(null; $e)
end ;</syntaxhighlight>
'''Examples'''
<syntaxhighlight lang="jq">0.9054054,
0.518518,
0.75,
1e308
| "\(.) → \(number_to_r | rpp)"</syntaxhighlight>
{{out}}
<pre>
0.9054054 → 4527027 // 5000000
0.518518 → 259259 // 500000
0.75 → 3 // 4
1e+308 → 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 // 1
</pre>
 
=={{header|Julia}}==
Julia has a native Rational type, and provides [http://docs.julialang.org/en/latest/manual/conversion-and-promotion/#case-study-rational-conversions a convenience conversion function] that implements a standard algorithm for approximating a floating-point number by a ratio of integers to within a given tolerance, which defaults to machine epsilon.
 
<langsyntaxhighlight Julialang="julia">rationalize(0.9054054)
rationalize(0.518518)
rationalize(0.75)</langsyntaxhighlight>
 
4527027//5000000
Line 1,238 ⟶ 1,668:
Here is the core algorithm written in Julia 1.0, without handling various data types and corner cases:
 
<langsyntaxhighlight Julialang="julia">function rat(x::AbstractFloat, tol::Real=eps(x))::Rational
p, q, pp, qq = copysign(1,x), 0, 0, 1
x, y = abs(x), 1.0
Line 1,257 ⟶ 1,687:
i = Int(cld(x-tt,y+t)) # find optimal semiconvergent: smallest i such that x-i*y < i*t+tt
return (i*p+pp) // (i*q+qq)
end</langsyntaxhighlight>
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.1.2
 
class Rational(val num: Long, val den: Long) {
Line 1,288 ⟶ 1,718:
for (decimal in decimals)
println("${decimal.toString().padEnd(9)} = ${decimalToRational(decimal)}")
}</langsyntaxhighlight>
 
{{out}}
Line 1,303 ⟶ 1,733:
 
=={{header|Liberty BASIC}}==
<syntaxhighlight lang="lb">
<lang lb>
' Uses convention that one repeating sequence implies infinitely repeating sequence..
' Non-recurring fractions are limited to nd number of digits in nuerator & denominator
Line 1,379 ⟶ 1,809:
if length /2 =int( length /2) then if mid$( i$, 3, length /2) =mid$( i$, 3 +length /2, length /2) then check$ ="recurring"
end function
</syntaxhighlight>
</lang>
<pre>
0.5 is non-recurring
Line 1,412 ⟶ 1,842:
END.
</pre>
 
=={{header|Lua}}==
Brute force, and why not?
<syntaxhighlight lang="lua">for _,v in ipairs({ 0.9054054, 0.518518, 0.75, math.pi }) do
local n, d, dmax, eps = 1, 1, 1e7, 1e-15
while math.abs(n/d-v)>eps and d<dmax do d=d+1 n=math.floor(v*d) end
print(string.format("%15.13f --> %d / %d", v, n, d))
end</syntaxhighlight>
{{out}}
<pre>0.9054054000000 --> 4527027 / 5000000
0.5185180000000 --> 259259 / 500000
0.7500000000000 --> 3 / 4
3.1415926535898 --> 31415926 / 10000000</pre>
 
=={{header|M2000 Interpreter}}==
 
<syntaxhighlight lang="m2000 interpreter">
module Convert_decimal_number_to_rational{
Function Rational(numerator as decimal, denominator as decimal=1) {
if denominator==0 then denominator=1
while frac(numerator)<>0 {
numerator*=10@
denominator*=10@
}
sgn=Sgn(numerator)*Sgn(denominator)
denominator<=abs(denominator)
numerator<=abs(numerator)*sgn
gcd1=lambda (a as decimal, b as decimal) -> {
if a<b then swap a,b
g=a mod b
while g {a=b:b=g: g=a mod b}
=abs(b)
}
gdcval=gcd1(abs(numerator), denominator)
if gdcval<denominator and gdcval<>0 then
denominator/=gdcval
numerator/=gdcval
end if
=(numerator,denominator)
}
Print Rational(0.9054054)#str$(" / ")="4527027 / 5000000" ' true
Print Rational(0.518518)#str$(" / ")="259259 / 500000" ' true
Print Rational(0.75)#str$(" / ")="3 / 4" ' true
}
Convert_decimal_number_to_rational
</syntaxhighlight>
 
=={{header|Maple}}==
<syntaxhighlight lang="maple">
<lang Maple>
> map( convert, [ 0.9054054, 0.518518, 0.75 ], 'rational', 'exact' );
4527027 259259
[-------, ------, 3/4]
5000000 500000
</syntaxhighlight>
</lang>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">Map[Rationalize[#,0]&,{0.9054054,0.518518, 0.75} ]
-> {4527027/5000000,259259/500000,3/4}</langsyntaxhighlight>
 
=={{header|MATLAB}} / {{header|Octave}}==
<syntaxhighlight lang="matlab">
<lang Matlab>
[a,b]=rat(.75)
[a,b]=rat(.518518)
[a,b]=rat(.9054054)
</syntaxhighlight>
</lang>
 
Output:
Line 1,449 ⟶ 1,926:
{{improve|МК-61/52|This example is not clear, please improve it or delete it!}}
 
<syntaxhighlight lang="text">П0 П1 ИП1 {x} x#0 14 КИП4 ИП1 1 0
* П1 БП 02 ИП4 10^x П0 ПA ИП1 ПB
ИПA ИПB / П9 КИП9 ИПA ИПB ПA ИП9 *
- ПB x=0 20 ИПA ИП0 ИПA / П0 ИП1
ИПA / П1 ИП0 ИП1 С/П</langsyntaxhighlight>
 
=={{header|NetRexx}}==
Now the nearly equivalent program.
<langsyntaxhighlight lang="netrexx">
/*NetRexx program to convert decimal numbers to fractions *************
* 16.08.2012 Walter Pachl derived from Rexx Version 2
Line 1,518 ⟶ 1,995:
end
If den=1 Then Return nom /* an integer */
Else Return nom'/'den /* otherwise a fraction */</langsyntaxhighlight>
Output is the same as for Rexx Version 2.
 
=={{header|Nim}}==
Similar to the Rust and Julia implementations.
<langsyntaxhighlight lang="nim">import math
import fenv
 
Line 1,578 ⟶ 2,055:
echo rationalize(0.99)
echo rationalize(0.909)
echo rationalize(0.909, 0.001)</langsyntaxhighlight>
 
{{out}}
Line 1,598 ⟶ 2,075:
Nim also has a rationals library for this, though it does not allow you to set tolerances like the code above.
 
<langsyntaxhighlight lang="nim">import rationals
 
echo toRational(0.9054054054)
Line 1,608 ⟶ 2,085:
echo toRational(0.9)
echo toRational(0.99)
echo toRational(0.909)</langsyntaxhighlight>
 
{{out}}
Line 1,621 ⟶ 2,098:
99/100
909/1000
</pre>
 
=={{header|Ol}}==
Any number in Ol by default is exact. It means that any number automatically converted into rational form. If you want to use real floating point numbers, use "#i" prefix.
 
Function `exact` creates exact number (possibly rational) from any inexact.
<syntaxhighlight lang="scheme">
(print (exact #i0.9054054054))
(print (exact #i0.5185185185))
(print (exact #i0.75))
(print (exact #i35.000))
(print (exact #i35.001))
(print (exact #i0.9))
(print (exact #i0.99))
(print (exact #i0.909))
</syntaxhighlight>
{{out}}
<pre>
4077583446378673/4503599627370496
4670399613402603/9007199254740992
3/4
35
4925952829924835/140737488355328
8106479329266893/9007199254740992
4458563631096791/4503599627370496
4093772061279781/4503599627370496
</pre>
 
=={{header|PARI/GP}}==
Quick and dirty.
<langsyntaxhighlight lang="parigp">convert(x)={
my(n=0);
while(x-floor(x*10^n)/10^n!=0.,n++);
floor(x*10^n)/10^n
};</langsyntaxhighlight>
 
To convert a number into a rational with a denominator not dividing a power of 10, use <code>contfrac</code> and the Gauss-Kuzmin distribution to distinguish (hopefully!) where to truncate.
Line 1,635 ⟶ 2,138:
=={{header|Perl}}==
Note: the following is considerably more complicated than what was specified, because the specification is not, well, specific. Three methods are provided with different interpretation of what "conversion" means: keeping the string representation the same, keeping machine representation the same, or find best approximation with denominator in a reasonable range. None of them takes integer overflow seriously (though the best_approx is not as badly subject to it), so not ready for real use.
<langsyntaxhighlight lang="perl">sub gcd {
my ($m, $n) = @_;
($m, $n) = ($n, $m % $n) while $n;
Line 1,763 ⟶ 2,266:
for (map { 10 ** $_ } 1 .. 10) {
printf "approx below %g: %d / %d\n", $_, best_approx($x, $_)
}</langsyntaxhighlight>
Output: <pre>3/8 = 0.375:
machine: 3/8
Line 1,797 ⟶ 2,300:
approx below 1e+09: -1881244168 / 598818617
approx below 1e+10: -9978066541 / 3176117225</pre>
 
=={{header|Perl 6}}==
Decimals are natively represented as rationals in Perl 6, so if the task does not need to handle repeating decimals, it is trivially handled by the <tt>.nude</tt> method, which returns the numerator and denominator:
<lang perl6>say .nude.join('/') for 0.9054054, 0.518518, 0.75;</lang>
{{out}}
<pre>4527027/5000000
259259/500000
3/4</pre>
However, if we want to take repeating decimals into account, then we can get a bit fancier.
<lang perl6>sub decimal_to_fraction ( Str $n, Int $rep_digits = 0 ) returns Str {
my ( $int, $dec ) = ( $n ~~ /^ (\d+) \. (\d+) $/ )».Str or die;
 
my ( $numer, $denom ) = ( $dec, 10 ** $dec.chars );
if $rep_digits {
my $to_move = $dec.chars - $rep_digits;
$numer -= $dec.substr(0, $to_move);
$denom -= 10 ** $to_move;
}
 
my $rat = Rat.new( $numer.Int, $denom.Int ).nude.join('/');
return $int > 0 ?? "$int $rat" !! $rat;
}
 
my @a = ['0.9054', 3], ['0.518', 3], ['0.75', 0], | (^4).map({['12.34567', $_]});
for @a -> [ $n, $d ] {
say "$n with $d repeating digits = ", decimal_to_fraction( $n, $d );
}</lang>
{{out}}
<pre>0.9054 with 3 repeating digits = 67/74
0.518 with 3 repeating digits = 14/27
0.75 with 0 repeating digits = 3/4
12.34567 with 0 repeating digits = 12 34567/100000
12.34567 with 1 repeating digits = 12 31111/90000
12.34567 with 2 repeating digits = 12 17111/49500
12.34567 with 3 repeating digits = 12 1279/3700</pre>
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>function decrat(string s)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
integer nom = 0
<span style="color: #008080;">function</span> <span style="color: #000000;">decrat</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
integer denom = 1
<span style="color: #004080;">integer</span> <span style="color: #000000;">nom</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span>
if s[1..2]!="0." then ?9/0 end if
<span style="color: #000000;">denom</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
for i=3 to length(s) do
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">"0."</span><span style="color: #0000FF;">)</span>
integer ch = s[i]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">3</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
if ch<'0' or ch>'9' then ?9/0 end if
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
nom = nom*10 + ch-'0'
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">>=</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><=</span><span style="color: #008000;">'9'</span><span style="color: #0000FF;">)</span>
denom *= 10
<span style="color: #000000;">nom</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">nom</span><span style="color: #0000FF;">*</span><span style="color: #000000;">10</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">-</span><span style="color: #008000;">'0'</span>
end for
<span style="color: #000000;">denom</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">10</span>
return sq_div({nom,denom},gcd(nom,denom))
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sq_div</span><span style="color: #0000FF;">({</span><span style="color: #000000;">nom</span><span style="color: #0000FF;">,</span><span style="color: #000000;">denom</span><span style="color: #0000FF;">},</span><span style="color: #7060A8;">gcd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nom</span><span style="color: #0000FF;">,</span><span style="color: #000000;">denom</span><span style="color: #0000FF;">))</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
?decrat("0.9054054")
?decrat("0.518518")
<span style="color: #0000FF;">?</span><span style="color: #000000;">decrat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"0.9054054"</span><span style="color: #0000FF;">)</span>
?decrat("0.75")</lang>
<span style="color: #0000FF;">?</span><span style="color: #000000;">decrat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"0.518518"</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">decrat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"0.75"</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 1,859 ⟶ 2,330:
=={{header|PHP}}==
{{works with|PHP|5.3+}}
<langsyntaxhighlight lang="php">function asRational($val, $tolerance = 1.e-6)
{
if ($val == (int) $val) {
Line 1,890 ⟶ 2,361:
echo asRational(1/4)."\n"; // "1/4"
echo asRational(1/3)."\n"; // "1/3"
echo asRational(5)."\n"; // "5"</langsyntaxhighlight>
 
=={{header|PL/I}}==
<syntaxhighlight lang="text">(size, fofl):
Convert_Decimal_To_Rational: procedure options (main); /* 14 January 2014, from Ada */
 
Line 1,946 ⟶ 2,417:
end;
end;
end Convert_Decimal_To_Rational;</langsyntaxhighlight>
Output:
<pre>
Line 1,963 ⟶ 2,434:
 
=={{header|PureBasic}}==
<langsyntaxhighlight lang="purebasic">Procedure.i ggT(a.i, b.i)
Define t.i : If a < b : Swap a, b : EndIf
While a%b : t=a : a=b : b=t%a : Wend : ProcedureReturn b
Line 1,986 ⟶ 2,457:
DataSection
Data.d 0.9054054,0.518518,0.75,0.0
EndDataSection</langsyntaxhighlight>
<pre>
0.9054054 -> 4527027/5000000
Line 1,998 ⟶ 2,469:
 
The first loop limits the size of the denominator, because the floating-point representation is not exact. The second converts the string representation of the given values directly to fractions.
<langsyntaxhighlight lang="python">>>> from fractions import Fraction
>>> for d in (0.9054054, 0.518518, 0.75): print(d, Fraction.from_float(d).limit_denominator(100))
 
Line 2,009 ⟶ 2,480:
0.518518 259259/500000
0.75 3/4
>>> </langsyntaxhighlight>
 
 
Or, writing our own '''approxRatio''' function:
{{Works with|Python|3.7}}
<langsyntaxhighlight lang="python">'''Approximate rationals from decimals'''
 
from math import (floor, gcd)
Line 2,132 ⟶ 2,603:
# MAIN ---
if __name__ == '__main__':
main()</langsyntaxhighlight>
{{Out}}
<pre>Approximate rationals from decimals (epsilon of 1/10000):
Line 2,148 ⟶ 2,619:
 
=={{header|R}}==
<syntaxhighlight lang="r">
<lang R>
ratio<-function(decimal){
denominator=1
Line 2,158 ⟶ 2,629:
return(str)
}
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 2,168 ⟶ 2,639:
[1] "157/50"
</pre>
 
=={{header|Quackery}}==
 
Using the Quackery big number rational arithmetic library <code>bigrat.qky</code>.
 
<syntaxhighlight lang="quackery">[ $ "bigrat.qky" loadfile ] now!
 
[ dup echo$
say " is "
$->v drop
dup 100 > if
[ say "approximately "
proper 100 round
improper ]
vulgar$ echo$
say "." cr ] is task ( $ --> )
 
$ "0.9054054 0.518518 0.75" nest$ witheach task</syntaxhighlight>
 
{{out}}
 
<pre>0.9054054 is approximately 67/74.
0.518518 is approximately 14/27.
0.75 is 3/4.</pre>
 
=={{header|Racket}}==
Racket has builtin exact and inexact representantions of numbers, 3/4 is a valid number syntactically, and one can change between the exact and inexact values with the functions showed in the example.
They have some amount of inaccuracy, but i guess it can be tolerated.
<langsyntaxhighlight Racketlang="racket">#lang racket
 
(inexact->exact 0.75) ; -> 3/4
Line 2,178 ⟶ 2,673:
 
(exact->inexact 67/74) ; -> 0.9054054054054054
(inexact->exact 0.9054054054054054) ;-> 8155166892806033/9007199254740992</langsyntaxhighlight>
 
=={{header|Raku}}==
(formerly Perl 6)
Decimals are natively represented as rationals in Raku, so if the task does not need to handle repeating decimals, it is trivially handled by the <tt>.nude</tt> method, which returns the numerator and denominator:
<syntaxhighlight lang="raku" line>say .nude.join('/') for 0.9054054, 0.518518, 0.75;</syntaxhighlight>
{{out}}
<pre>4527027/5000000
259259/500000
3/4</pre>
However, if we want to take repeating decimals into account, then we can get a bit fancier.
<syntaxhighlight lang="raku" line>sub decimal_to_fraction ( Str $n, Int $rep_digits = 0 ) returns Str {
my ( $int, $dec ) = ( $n ~~ /^ (\d+) \. (\d+) $/ )».Str or die;
 
my ( $numer, $denom ) = ( $dec, 10 ** $dec.chars );
if $rep_digits {
my $to_move = $dec.chars - $rep_digits;
$numer -= $dec.substr(0, $to_move);
$denom -= 10 ** $to_move;
}
 
my $rat = Rat.new( $numer.Int, $denom.Int ).nude.join('/');
return $int > 0 ?? "$int $rat" !! $rat;
}
 
my @a = ['0.9054', 3], ['0.518', 3], ['0.75', 0], | (^4).map({['12.34567', $_]});
for @a -> [ $n, $d ] {
say "$n with $d repeating digits = ", decimal_to_fraction( $n, $d );
}</syntaxhighlight>
{{out}}
<pre>0.9054 with 3 repeating digits = 67/74
0.518 with 3 repeating digits = 14/27
0.75 with 0 repeating digits = 3/4
12.34567 with 0 repeating digits = 12 34567/100000
12.34567 with 1 repeating digits = 12 31111/90000
12.34567 with 2 repeating digits = 12 17111/49500
12.34567 with 3 repeating digits = 12 1279/3700</pre>
 
=={{header|REXX}}==
Line 2,206 ⟶ 2,737:
<br>REXX can support almost any number of decimal digits, but &nbsp; '''10''' &nbsp; was chosen for practicality for this task.
<langsyntaxhighlight lang="rexx">/*REXX program converts a rational fraction [n/m] (or nnn.ddd) to it's lowest terms.*/
numeric digits 10 /*use ten decimal digits of precision. */
parse arg orig 1 n.1 "/" n.2; if n.2='' then n.2=1 /*get the fraction.*/
Line 2,232 ⟶ 2,763:
end /*while*/
if h==1 then return b /*don't return number ÷ by 1.*/
return b'/'h /*proper or improper fraction. */</langsyntaxhighlight>
'''output''' &nbsp; when using various inputs (which are displayed as part of the output):
<br>(Multiple runs are shown, outputs are separated by a blank line.)
Line 2,256 ⟶ 2,787:
 
===version 2===
<langsyntaxhighlight lang="rexx">/*REXX program to convert decimal numbers to fractions ****************
* 15.08.2012 Walter Pachl derived from above for readability
* It took me time to understand :-) I need descriptive variable names
Line 2,325 ⟶ 2,856:
if den=1 then return nom /* denominator 1: integer */
return nom'/'den /* otherwise a fraction */
</syntaxhighlight>
</lang>
Output:
<pre>
Line 2,354 ⟶ 2,885:
 
===version 3===
<langsyntaxhighlight lang="rexx">/* REXX ---------------------------------------------------------------
* 13.02.2014 Walter Pachl
* specify the number as xxx.yyy(pqr) pqr is the period
Line 2,414 ⟶ 2,945:
Parse Arg a,b
if b = 0 then return abs(a)
return GCD(b,a//b)</langsyntaxhighlight>
'''Output:'''
<pre>5.55555 = 111111/20000 ok
Line 2,431 ⟶ 2,962:
0.00000000001 = 1/100000000000 ok
0.000001000001 = 1000001/1000000000000 ok</pre>
 
=={{header|RPL}}==
Starting with HP-48 versions, the conversion can be performed directly with the <code>→Q</code> instruction. Earlier versions must instead use the following code, which is based on continued fractions.
{{works with|Halcyon Calc|4.2.8}}
{| class="wikitable"
! RPL code
! Comment
|-
|
ABS LAST SIGN 1E6 → sign dmax
≪ (0,1) (1,0)
'''DO'''
SWAP OVER 4 ROLL INV IP
LAST FP 5 ROLLD
* +
'''UNTIL''' DUP2 IM SWAP IM * dmax >
4 PICK dmax INV < OR '''END'''
ROT ROT DROP2
"'" OVER RE sign * →STR + "/" +
SWAP IM →STR + STR→
≫ ≫ '<span style="color:blue">→PQ</span>' STO
|
<span style="color:blue">'''→PQ'''</span> ''( x → 'p/q' ) ''
store sign(x) and max denominator
a(0) = x ; hk(-2) = (0,1) ; hk(-1) = (1,0)
loop
reorder int(a(n)), hk(n-1) and hk(n-2) in stack
a(n+1)=1/frac(a(n)) back to top of stack
hk(n) = a(n)*hk(n-1) + hk(n-2)
until k(n)*(kn-1) > max denominator or
a(n+1) > max denominator
clean stack
convert a(n) from (p,q) to 'p/q' format
return 'p/q'
|}
.518518 <span style="color:blue">'''→PQ'''</span>
.905405405405 <span style="color:blue">'''→PQ'''</span>
-3.875 <span style="color:blue">'''→PQ'''</span>
'''Output:'''
<span style="color:grey"> 3:</span> '37031/71417'
<span style="color:grey"> 2:</span> '67/74'
<span style="color:grey"> 1:</span> '-31/8'
 
=={{header|Ruby}}==
Line 2,437 ⟶ 3,012:
 
This converts the string representation of the given values directly to fractions.
<langsyntaxhighlight lang="ruby">> '0.9054054 0.518518 0.75'.split.each { |d| puts "%s %s" % [d, Rational(d)] }
0.9054054 4527027/5000000
0.518518 259259/500000
0.75 3/4
=> ["0.9054054", "0.518518", "0.75"]</langsyntaxhighlight>
 
This loop finds the simplest fractions within a given radius, because the floating-point representation is not exact.
<langsyntaxhighlight lang="ruby">[0.9054054, 0.518518, 0.75].each { |f| puts "#{f} #{f.rationalize(0.0001)}" }
# =>0.9054054 67/74
# =>0.518518 14/27
# =>0.75 3/4
</syntaxhighlight>
</lang>
{{works with|Ruby|2.1.0+}}
A suffix for integer and float literals was introduced:
Line 2,462 ⟶ 3,037:
 
=={{header|Rust}}==
<syntaxhighlight lang="text">
extern crate rand;
extern crate num;
Line 2,521 ⟶ 3,096:
}
}
</syntaxhighlight>
</lang>
First test the function with 1_000_000 random double floats :
<pre>
Line 2,552 ⟶ 3,127:
=={{header|Scala}}==
{{Out}}Best seen running in your browser [https://scastie.scala-lang.org/rrlFnuTURgirBiTsH3Kqrg Scastie (remote JVM)].
<langsyntaxhighlight Scalalang="scala">import org.apache.commons.math3.fraction.BigFraction
 
object Number2Fraction extends App {
Line 2,559 ⟶ 3,134:
for (d <- n)
println(f"$d%-12s : ${new BigFraction(d, 0.00000002D, 10000)}%s")
}</langsyntaxhighlight>
 
=={{header|Seed7}}==
The library [http://seed7.sourceforge.net/libraries/bigrat.htm bigrat.s7i]
defines the operatorfunction [httphttps://seed7.sourceforge.net/libraries/bigrat.htm#%28attr_bigRational%29parse%28in_var_string%29bigRational(in_var_string) parsebigRational],
which creates a [https://seed7.sourceforge.net/manual/types.htm#bigRational bigRational] number from a string.
which accepts, besides fractions, also a decimal number with repeating decimals.
This function accepts, besides fractions, also a decimal number with repeating decimals.
<lang seed7>$ include "seed7_05.s7i";
Internally a bigRational uses numerator and denominator to represent a rational number.
Writing a bigRational does not create a fraction with numerator and denominator, but a decimal number with possibly repeating decimals.
The function [https://seed7.sourceforge.net/libraries/bigrat.htm#fraction(in_bigRational) fraction]
uses numerator and denominator from the bigRational number to get a string with the fraction.
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "bigrat.s7i";
 
Line 2,583 ⟶ 3,163:
writeln(bigRational parse "31.415926536");
writeln(bigRational parse "0.000000000");
end func;</lang>
writeln;
 
writeln(fraction(bigRational("0.9(054)")));
writeln(fraction(bigRational("0.(518)")));
writeln(fraction(bigRational("0.75")));
writeln(fraction(bigRational("3.(142857)")));
writeln(fraction(bigRational("0.(8867924528301)")));
writeln(fraction(bigRational("0.(846153)")));
writeln(fraction(bigRational("0.9054054")));
writeln(fraction(bigRational("0.518518")));
writeln(fraction(bigRational("0.14285714285714")));
writeln(fraction(bigRational("3.14159265358979")));
writeln(fraction(bigRational("2.718281828")));
writeln(fraction(bigRational("31.415926536")));
writeln(fraction(bigRational("0.000000000")));
end func;</syntaxhighlight>
{{out}}
<pre>67/74
0.9(054)
0.(518)
0.75
3.(142857)
0.(8867924528301)
0.(846153)
0.9054054
0.518518
0.14285714285714
3.14159265358979
2.718281828
31.415926536
0.0
 
67/74
14/27
3/4
Line 2,597 ⟶ 3,208:
679570457/250000000
3926990817/125000000
0/1</pre>
</pre>
 
=={{header|Sidef}}==
By default, literal numbers are represented in rational form:
This can be done by using the ''to_r'' method, which converts a scalar-object into a rational number:
<syntaxhighlight lang="ruby">say 0.75.as_frac #=> 3/4
<lang ruby>'0.9054054 0.518518 0.75'.split.each { |d|
say 0.518518.as_frac #=> 259259/500000
say d.num.as_rat;
say 0.9054054.as_frac #=> 4527027/5000000</syntaxhighlight>
}</lang>
 
Additionally, '''Num(str)''' can be used for parsing a decimal expansion into rational form:
Another way is by calling the ''rat'' method on Number objects:
<langsyntaxhighlight lang="ruby">say '0.9054054 0.as_rat;518518 0.75'.split.each { |str|
say 0.518518Num(str).as_rat;as_frac
}</syntaxhighlight>
say 0.75.as_rat;</lang>
 
{{out}}
Line 2,616 ⟶ 3,228:
3/4
</pre>
 
For rational approximations, the Number '''.rat_approx''' method can be used:
<syntaxhighlight lang="ruby">say 0.518518.rat_approx.as_frac #=> 14/27
say 0.9054054.rat_approx.as_frac #=> 67/74</syntaxhighlight>
 
=={{header|Tcl}}==
{{works with|Tcl|8.4+}}
Here is a complete script with the implemented function and a small test suite (which is executed when this script is called directly from a shell) - originally on http://wiki.tcl.tk/752:
<langsyntaxhighlight Tcllang="tcl">#!/usr/bin/env tclsh
 
proc dbl2frac {dbl {eps 0.000001}} {
Line 2,641 ⟶ 3,257:
}
}
}</langsyntaxhighlight>
Running it shows one unexpected result, but on closer examination it is clear that 14/27 equals 42/81, so it should indeed be the right solution:
~ $ fractional.tcl
dbl2frac 0.518518 -> 14 27, expected 42 81
~ $
 
=={{header|TI SR-56}}==
{| class="wikitable"
|+ Texas Instruments SR-56 Program Listing for "Convert decimal number to rational"
|-
! Display !! Key !! Display !! Key !! Display !! Key !! Display !! Key
|-
| 00 33 || STO || 25 00 || 0 || 50 || || 75 ||
|-
| 01 00 || 0 || 26 64 || * || 51 || || 76 ||
|-
| 02 00 || 0 || 27 34 || RCL || 52 || || 77 ||
|-
| 03 33 || STO || 28 01 || 1 || 53 || || 78 ||
|-
| 04 01 || 1 || 29 94 || = || 54 || || 79 ||
|-
| 05 56 || *CP || 30 41 || R/S || 55 || || 80 ||
|-
| 06 01 || 1 || 31 || || 56 || || 81 ||
|-
| 07 35 || SUM || 32 || || 57 || || 82 ||
|-
| 08 01 || 1 || 33 || || 58 || || 83 ||
|-
| 09 34 || RCL || 34 || || 59 || || 84 ||
|-
| 10 01 || 1 || 35 || || 60 || || 85 ||
|-
| 11 64 || * || 36 || || 61 || || 86 ||
|-
| 12 34 || RCL || 37 || || 62 || || 87 ||
|-
| 13 00 || 0 || 38 || || 63 || || 88 ||
|-
| 14 94 || = || 39 || || 64 || || 89 ||
|-
| 15 12 || Inv || 40 || || 65 || || 90 ||
|-
| 16 29 || *Int || 41 || || 66 || || 91 ||
|-
| 17 12 || Inv || 42 || || 67 || || 92 ||
|-
| 18 37 || *x=t || 43 || || 68 || || 93 ||
|-
| 19 00 || 0 || 44 || || 69 || || 94 ||
|-
| 20 06 || 6 || 45 || || 70 || || 95 ||
|-
| 21 34 || RCL || 46 || || 71 || || 96 ||
|-
| 22 01 || 1 || 47 || || 72 || || 97 ||
|-
| 23 32 || x<>t || 48 || || 73 || || 98 ||
|-
| 24 34 || RCL || 49 || || 74 || || 99 ||
|}
 
Asterisk denotes 2nd function key.
 
{| class="wikitable"
|+ Register allocation
|-
| 0: Decimal || 1: Denominator|| 2: Unused || 3: Unused || 4: Unused
|-
| 5: Unused || 6: Unused || 7: Unused || 8: Unused || 9: Unused
|}
 
Annotated listing:
<syntaxhighlight lang="text">
STO 0 // Decimal := User Input
0 STO 1 // Denominator := 0
*CP // RegT := 0
1 SUM 1 // Denominator += 1
RCL 1 * RCL 0 = Inv *Int // Find fractional part of Decimal * Denominator
Inv *x=t 0 6 // If it is nonzero loop back to instruction 6
RCL 1 x<>t // Report denominator
RCL 0 * RCL 1 = // Report numerator
R/S // End
</syntaxhighlight>
 
'''Usage:'''
 
Enter the decimal and then press RST R/S. Once a suitable rational is found, the numerator will be displayed. Press x<>t to toggle between the numerator and denominator.
 
{{in}}
 
0.875 RST R/S
 
{{out}}
 
After about five seconds, '''3''' will appear on the screen. Press x<>t and '''8''' will appear on the screen. The fraction is 3/8.
 
Any fraction with denominator <=100 is found in 1 minute or less. 100 denominators are checked per minute.
 
=={{header|Vala}}==
{{trans|C}}
<langsyntaxhighlight lang="vala">struct Fraction {
public long d;
public long n;
Line 2,704 ⟶ 3,414:
print("%11ld/%ld\n", r.n, r.d);
}
}</langsyntaxhighlight>
 
{{out}}
Line 2,724 ⟶ 3,434:
denom <= 1048576: 3126535/995207
denom <= 16777216: 47627751/15160384
</pre>
 
=={{header|VBA}}==
{{trans|D}}
<syntaxhighlight lang="vb">Function Real2Rational(r As Double, bound As Long) As String
 
If r = 0 Then
Real2Rational = "0/1"
ElseIf r < 0 Then
Result = Real2Rational(-r, bound)
Real2Rational = "-" & Result
Else
best = 1
bestError = 1E+99
For i = 1 To bound + 1
currentError = Abs(i * r - Round(i * r))
If currentError < bestError Then
best = i
bestError = currentError
If bestError < 1 / bound Then GoTo SkipLoop
End If
Next i
SkipLoop:
Real2Rational = Round(best * r) & "/" & best
End If
End Function
 
Sub TestReal2Rational()
Debug.Print "0.75" & ":";
For i = 0 To 5
Order = CDbl(10) ^ CDbl(i)
Debug.Print " " & Real2Rational(0.75, CLng(Order));
Next i
Debug.Print
 
Debug.Print "0.518518" & ":";
For i = 0 To 5
Order = CDbl(10) ^ CDbl(i)
Debug.Print " " & Real2Rational(0.518518, CLng(Order));
Next i
Debug.Print
 
Debug.Print "0.9054054" & ":";
For i = 0 To 5
Order = CDbl(10) ^ CDbl(i)
Debug.Print " " & Real2Rational(0.9054054, CLng(Order));
Next i
Debug.Print
 
Debug.Print "0.142857143" & ":";
For i = 0 To 5
Order = CDbl(10) ^ CDbl(i)
Debug.Print " " & Real2Rational(0.142857143, CLng(Order));
Next i
Debug.Print
 
Debug.Print "3.141592654" & ":";
For i = 0 To 5
Order = CDbl(10) ^ CDbl(i)
Debug.Print " " & Real2Rational(3.141592654, CLng(Order));
Next i
Debug.Print
 
Debug.Print "2.718281828" & ":";
For i = 0 To 5
Order = CDbl(10) ^ CDbl(i)
Debug.Print " " & Real2Rational(2.718281828, CLng(Order));
Next i
Debug.Print
 
Debug.Print "-0.423310825" & ":";
For i = 0 To 5
Order = CDbl(10) ^ CDbl(i)
Debug.Print " " & Real2Rational(-0.423310825, CLng(Order));
Next i
Debug.Print
 
Debug.Print "31.415926536" & ":";
For i = 0 To 5
Order = CDbl(10) ^ CDbl(i)
Debug.Print " " & Real2Rational(31.415926536, CLng(Order));
Next i
End Sub
</syntaxhighlight>
{{out}}
<pre>
0.75: 1/1 3/4 3/4 3/4 3/4 3/4
0.518518: 1/1 1/2 14/27 14/27 14/27 37031/71417
0.9054054: 1/1 1/1 67/74 67/74 67/74 67/74
0.142857143: 0/1 1/7 1/7 1/7 1/7 1/7
3.141592654: 3/1 22/7 22/7 355/113 355/113 104348/33215
2.718281828: 3/1 19/7 193/71 1457/536 23225/8544 173459/63812
-0.423310825: -0/1 -3/7 -11/26 -69/163 -1253/2960 -10093/23843
31.415926536: 31/1 157/5 377/12 3550/113 208696/6643 1563445/49766
</pre>
 
=={{header|Wren}}==
{{libheader|Wren-rat}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./rat" for Rat
import "./fmt" for Fmt
 
var tests = [0.9054054, 0.518518, 0.75]
for (test in tests) {
var r = Rat.fromFloat(test)
System.print("%(Fmt.s(-9, test)) -> %(r)")
}</syntaxhighlight>
 
{{out}}
<pre>
0.9054054 -> 4527027/5000000
0.518518 -> 259259/500000
0.75 -> 3/4
</pre>
 
=={{header|zkl}}==
{{trans|D}}
<langsyntaxhighlight lang="zkl">fcn real2Rational(r,bound){
if (r == 0.0) return(0,1);
if (r < 0.0){
Line 2,741 ⟶ 3,564:
return((r*best).round().toInt(),best);
}
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">tests := T(0.750000000, 0.518518000, 0.905405400,
0.142857143, 3.141592654, 2.718281828,
-0.423310825, 31.415926536);
Line 2,750 ⟶ 3,573:
{ print(" %d/%d".fmt(real2Rational(r,(10).pow(i)).xplode())) }
println();
}</langsyntaxhighlight>
{{out}}
<pre>
871

edits