Jump to content

Convert decimal number to rational: Difference between revisions

New post.
(New post.)
 
(14 intermediate revisions by 7 users not shown)
Line 662:
3.14159265358979 → 104348 / 33215
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 1,177 ⟶ 1,266:
print n & ":", parserational(n)
loop</syntaxhighlight>
 
=={{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}}
Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. 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 storage and transfer purposes more than visualization and edition.
 
'''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]]
Programs in Fōrmulæ are created/edited online in its [https://formulae.org website], However they run on execution servers. By default remote servers are used, but they are limited in memory and processing power, since they are intended for demonstration and casual use. A local server can be downloaded and installed, it has no limitations (it runs in your own computer). Because of that, example programs can be fully visualized and edited, but some of them will not run if they require a moderate or heavy computation/memory resources, and no local server is being used.
 
[[File:Fōrmulæ - Convert decimal number to rational 20.png]]
In '''[https://formulae.org/?example=Convert_decimal_number_to_rational this]''' page you can see the program(s) related to this task and their results.
 
=={{header|Go}}==
Line 1,351 ⟶ 1,510:
Deriving an approximation within a specified tolerance:
<syntaxhighlight lang="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 ---
Line 1,400 ⟶ 1,586:
})();</syntaxhighlight>
{{Out}}
<pre>[67/74
14/27
"67/74",
3/4</pre>
"14/27",
"3/4"
]</pre>
 
=={{header|jq}}==
Line 1,914 ⟶ 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>
 
Line 2,752 ⟶ 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,896 ⟶ 3,150:
const proc: main is func
begin
writeln(bigRational parse "0.9(054)");
writeln(bigRational parse "0.(518)");
writeln(bigRational parse "0.75");
writeln(bigRational parse "3.(142857)");
writeln(bigRational parse "0.(8867924528301)");
writeln(bigRational parse "0.(846153)");
writeln(bigRational parse "0.9054054");
writeln(bigRational parse "0.518518");
writeln(bigRational parse "0.14285714285714");
writeln(bigRational parse "3.14159265358979");
writeln(bigRational parse "2.718281828");
writeln(bigRational parse "31.415926536");
writeln(bigRational parse "0.000000000");
writeln;
 
writeln(fraction(bigRational("0.9(054)")));
writeln(fraction(bigRational("0.(518)")));
Line 2,911 ⟶ 3,181:
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,923 ⟶ 3,208:
679570457/250000000
3926990817/125000000
0/1</pre>
</pre>
 
=={{header|Sidef}}==
Line 3,247 ⟶ 3,533:
{{libheader|Wren-rat}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="ecmascriptwren">import "./rat" for Rat
import "./fmt" for Fmt
 
var tests = [0.9054054, 0.518518, 0.75]
871

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.