Convert decimal number to rational: Difference between revisions

New post.
(New post.)
(9 intermediate revisions by 6 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æ}}==
Line 1,184 ⟶ 1,285:
'''Solution'''
 
'''Case 1.=== Without repeating digits'''===
 
The Fōrmulæ '''Rationalize''' expression converts from decimal numberts to rational in lower terms.
Line 1,191 ⟶ 1,292:
 
[[File:Fōrmulæ - Convert decimal number to rational 02.png]]
 
 
[[File:Fōrmulæ - Convert decimal number to rational 03.png]]
Line 1,196 ⟶ 1,298:
[[File:Fōrmulæ - Convert decimal number to rational 04.png]]
 
'''Case 2.=== 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.
Line 1,203 ⟶ 1,305:
 
[[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:
Line 1,213 ⟶ 1,316:
 
[[File:Fōrmulæ - Convert decimal number to rational 10.png]]
 
 
[https://en.wikipedia.org/wiki/0.999... 0.999... is actually 1]:
Line 1,220 ⟶ 1,324:
[[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:
Line 1,229 ⟶ 1,333:
 
[[File:Fōrmulæ - Convert decimal number to rational 15.png]]
 
 
[[File:Fōrmulæ - Convert decimal number to rational 16.png]]
Line 1,405 ⟶ 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,454 ⟶ 1,586:
})();</syntaxhighlight>
{{Out}}
<pre>[67/74
14/27
"67/74",
3/4</pre>
"14/27",
"3/4"
]</pre>
 
=={{header|jq}}==
Line 1,968 ⟶ 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,994 ⟶ 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 3,009 ⟶ 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 3,021 ⟶ 3,208:
679570457/250000000
3926990817/125000000
0/1</pre>
</pre>
 
=={{header|Sidef}}==
Line 3,345 ⟶ 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