Convert decimal number to rational: Difference between revisions

Content added Content deleted
(→‎{{header|JavaScript}}: Tidied, updated output.)
Line 1,409: Line 1,409:
Deriving an approximation within a specified tolerance:
Deriving an approximation within a specified tolerance:
<syntaxhighlight lang="javascript">(() => {
<syntaxhighlight lang="javascript">(() => {
'use strict';
"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 = () =>
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
gcde = (e, x, y) => {
const compose = (...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 = gcde(Boolean(eps) ? eps : (1 / 10000), 1, n);
(f, g) => x => f(g(x)),
return Ratio(
x => x
Math.floor(n / c), // numerator
Math.floor(1 / c) // denominator
);
);
};


// GENERIC FUNCTIONS ----------------------------------


// Ratio :: Int -> Int -> Ratio
// Ratio :: Int -> Int -> Ratio
const Ratio = (n, d) => ({
const Ratio = (n, d) => ({
type: 'Ratio',
type: "Ratio",
'n': n, // numerator
n,
'd': d // denominator
d
});
});


// 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
// showRatio :: Ratio -> String
const showRatio = nd =>
const showRatio = nd =>
nd.n.toString() + '/' + nd.d.toString();
`${nd.n.toString()}/${nd.d.toString()}`;



// MAIN ---
// MAIN ---
Line 1,458: Line 1,485:
})();</syntaxhighlight>
})();</syntaxhighlight>
{{Out}}
{{Out}}
<pre>[
<pre>67/74
14/27
"67/74",
3/4</pre>
"14/27",
"3/4"
]</pre>


=={{header|jq}}==
=={{header|jq}}==