Convert decimal number to rational: Difference between revisions
New post.
(New post.) |
|||
(19 intermediate revisions by 11 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}}
'''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}}==
Line 1,284 ⟶ 1,443:
=={{header|Java}}==
<syntaxhighlight lang="java">
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;
Line 1,308 ⟶ 1,510:
Deriving an approximation within a specified tolerance:
<syntaxhighlight lang="javascript">(() => {
// ---------------- 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 = () =>
[0.9054054, 0.518518, 0.75]
.map(
showRatio,
approxRatio(0.0001)
)
)
.join("\n");
// ---------------- GENERIC FUNCTIONS ----------------
// compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
const
// A function defined by the right-to-left
// composition of all the functions in fs.
);
// Ratio :: Int -> Int -> Ratio
const Ratio = (n, d) => ({
type:
});
// showRatio :: Ratio -> String
const showRatio = nd =>
`${nd.n.toString()
// MAIN ---
Line 1,357 ⟶ 1,586:
})();</syntaxhighlight>
{{Out}}
<pre>
14/27
3/4</pre>
=={{header|jq}}==
Line 1,628 ⟶ 1,855:
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}}==
Line 1,837 ⟶ 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,675 ⟶ 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,807 ⟶ 3,138:
=={{header|Seed7}}==
The library [http://seed7.sourceforge.net/libraries/bigrat.htm bigrat.s7i]
defines the
which creates a [https://seed7.sourceforge.net/manual/types.htm#bigRational bigRational] number from a string.
This function accepts, besides fractions, also a decimal number with repeating decimals.
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,827 ⟶ 3,163:
writeln(bigRational parse "31.415926536");
writeln(bigRational parse "0.000000000");
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>
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,841 ⟶ 3,208:
679570457/250000000
3926990817/125000000
0/1
</pre>
=={{header|Sidef}}==
Line 2,957 ⟶ 3,325:
|+ Register allocation
|-
| 0:
|-
| 5: Unused || 6: Unused || 7: Unused || 8: Unused || 9: Unused
Line 2,964 ⟶ 3,332:
Annotated listing:
<syntaxhighlight lang="text">
STO 0 //
0 STO 1 // Denominator := 0
*CP // RegT := 0
1 SUM 1 // Denominator += 1
RCL 1 * RCL 0 = Inv *Int // Find fractional part of
Inv *x=t 0 6 // If it is nonzero loop back to instruction 6
RCL 1 x<>t // Report denominator
Line 2,977 ⟶ 3,345:
'''Usage:'''
Enter the
{{in}}
Line 2,987 ⟶ 3,355:
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
=={{header|Vala}}==
Line 3,165 ⟶ 3,533:
{{libheader|Wren-rat}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="
import "./fmt" for Fmt
var tests = [0.9054054, 0.518518, 0.75]
|