Convert decimal number to rational: Difference between revisions
Content deleted Content added
m →{{header|Phix}}: added syntax colouring, marked p2js compatible |
Thundergnat (talk | contribs) m syntax highlighting fixup automation |
||
Line 24: | Line 24: | ||
{{trans|Nim}} |
{{trans|Nim}} |
||
< |
<syntaxhighlight lang="11l">T Rational |
||
Int numerator |
Int numerator |
||
Int denominator |
Int denominator |
||
Line 79: | Line 79: | ||
print(rationalize(0.99)) |
print(rationalize(0.99)) |
||
print(rationalize(0.909)) |
print(rationalize(0.909)) |
||
print(rationalize(0.909, 0.001))</ |
print(rationalize(0.909, 0.001))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 100: | Line 100: | ||
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, ...). |
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, ...). |
||
< |
<syntaxhighlight lang="ada">generic |
||
type Real is digits <>; |
type Real is digits <>; |
||
procedure Real_To_Rational(R: Real; |
procedure Real_To_Rational(R: Real; |
||
Bound: Positive; |
Bound: Positive; |
||
Nominator: out Integer; |
Nominator: out Integer; |
||
Denominator: out Positive);</ |
Denominator: out Positive);</syntaxhighlight> |
||
The implementation (just brute-force search for the best approximation with Denominator less or equal Bound): |
The implementation (just brute-force search for the best approximation with Denominator less or equal Bound): |
||
< |
<syntaxhighlight lang="ada">procedure Real_To_Rational (R: Real; |
||
Bound: Positive; |
Bound: Positive; |
||
Nominator: out Integer; |
Nominator: out Integer; |
||
Line 137: | Line 137: | ||
Nominator := Integer(Real'Rounding(Real(Denominator) * R)); |
Nominator := Integer(Real'Rounding(Real(Denominator) * R)); |
||
end Real_To_Rational;</ |
end Real_To_Rational;</syntaxhighlight> |
||
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: |
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: |
||
< |
<syntaxhighlight lang="ada">with Ada.Text_IO; With Real_To_Rational; |
||
procedure Convert_Decimal_To_Rational is |
procedure Convert_Decimal_To_Rational is |
||
Line 166: | Line 166: | ||
end loop; |
end loop; |
||
end Convert_Decimal_To_Rational; |
end Convert_Decimal_To_Rational; |
||
</syntaxhighlight> |
|||
</lang> |
|||
Finally, the output (reading the input from a file): |
Finally, the output (reading the input from a file): |
||
Line 183: | Line 183: | ||
=={{header|AppleScript}}== |
=={{header|AppleScript}}== |
||
< |
<syntaxhighlight lang="applescript">--------- RATIONAL APPROXIMATION TO DECIMAL NUMBER ------- |
||
-- approxRatio :: Real -> Real -> Ratio |
-- approxRatio :: Real -> Real -> Ratio |
||
Line 292: | Line 292: | ||
set my text item delimiters to dlm |
set my text item delimiters to dlm |
||
s |
s |
||
end unlines</ |
end unlines</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>0.9054054 -> 67/74 |
<pre>0.9054054 -> 67/74 |
||
Line 300: | Line 300: | ||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
< |
<syntaxhighlight lang="autohotkey"> Array := [] |
||
inputbox, string, Enter Number |
inputbox, string, Enter Number |
||
stringsplit, string, string, . |
stringsplit, string, string, . |
||
Line 386: | Line 386: | ||
MsgBox % String . " -> " . String1 . " " . Ans |
MsgBox % String . " -> " . String1 . " " . Ans |
||
reload |
reload |
||
</syntaxhighlight> |
|||
</lang> |
|||
<pre> |
<pre> |
||
0.9054054 -> 67/74 |
0.9054054 -> 67/74 |
||
Line 394: | Line 394: | ||
=={{header|Bracmat}}== |
=={{header|Bracmat}}== |
||
< |
<syntaxhighlight lang="bracmat">( ( exact |
||
= integerPart decimalPart z |
= integerPart decimalPart z |
||
. @(!arg:?integerPart "." ?decimalPart) |
. @(!arg:?integerPart "." ?decimalPart) |
||
Line 465: | Line 465: | ||
) |
) |
||
) |
) |
||
);</ |
);</syntaxhighlight> |
||
Output: |
Output: |
||
<pre>0.9054054054 = 4527027027/5000000000 (approx. 67/74) |
<pre>0.9054054054 = 4527027027/5000000000 (approx. 67/74) |
||
Line 483: | Line 483: | ||
=={{header|C}}== |
=={{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.< |
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.<syntaxhighlight lang="c">#include <stdio.h> |
||
#include <stdlib.h> |
#include <stdlib.h> |
||
#include <math.h> |
#include <math.h> |
||
Line 555: | Line 555: | ||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight>Output:<syntaxhighlight lang="text">f = 0.14285714285714 |
||
denom <= 1: 0/1 |
denom <= 1: 0/1 |
||
denom <= 16: 1/7 |
denom <= 16: 1/7 |
||
Line 571: | Line 571: | ||
denom <= 65536: 104348/33215 |
denom <= 65536: 104348/33215 |
||
denom <= 1048576: 3126535/995207 |
denom <= 1048576: 3126535/995207 |
||
denom <= 16777216: 47627751/15160384</ |
denom <= 16777216: 47627751/15160384</syntaxhighlight> |
||
=={{header|C sharp|C#}}== |
=={{header|C sharp|C#}}== |
||
{{trans|C}} |
{{trans|C}} |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
using System.Text; |
using System.Text; |
||
Line 651: | Line 651: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 700: | Line 700: | ||
=={{header|D}}== |
=={{header|D}}== |
||
{{trans|Ada}} |
{{trans|Ada}} |
||
< |
<syntaxhighlight lang="d">import std.stdio, std.math, std.string, std.typecons; |
||
alias Fraction = Tuple!(int,"nominator", uint,"denominator"); |
alias Fraction = Tuple!(int,"nominator", uint,"denominator"); |
||
Line 739: | Line 739: | ||
writeln(); |
writeln(); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>0.750000000 1/1 3/4 3/4 3/4 3/4 3/4 |
<pre>0.750000000 1/1 3/4 3/4 3/4 3/4 3/4 |
||
Line 754: | Line 754: | ||
Thanks Rudy Velthuis for Velthuis.BigRationals and Velthuis.BigDecimals library[https://github.com/rvelthuis/DelphiBigNumbers]. |
Thanks Rudy Velthuis for Velthuis.BigRationals and Velthuis.BigDecimals library[https://github.com/rvelthuis/DelphiBigNumbers]. |
||
{{Trans|Go}} |
{{Trans|Go}} |
||
<syntaxhighlight lang="delphi"> |
|||
<lang Delphi> |
|||
program Convert_decimal_number_to_rational; |
program Convert_decimal_number_to_rational; |
||
Line 778: | Line 778: | ||
end; |
end; |
||
Readln; |
Readln; |
||
end.</ |
end.</syntaxhighlight> |
||
=={{header|EchoLisp}}== |
=={{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 . |
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 . |
||
< |
<syntaxhighlight lang="scheme"> |
||
(exact->inexact 67/74) |
(exact->inexact 67/74) |
||
→ 0.9054054054054054 |
→ 0.9054054054054054 |
||
Line 809: | Line 809: | ||
"precision:10^-13 PI = 5419351/1725033" |
"precision:10^-13 PI = 5419351/1725033" |
||
"precision:10^-14 PI = 58466453/18610450" |
"precision:10^-14 PI = 58466453/18610450" |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
< |
<syntaxhighlight lang="factor">USING: kernel math.floating-point prettyprint ; |
||
0.9054054 0.518518 0.75 [ double>ratio . ] tri@</ |
0.9054054 0.518518 0.75 [ double>ratio . ] tri@</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 844: | Line 844: | ||
=={{header|Forth}}== |
=={{header|Forth}}== |
||
<syntaxhighlight lang="forth"> |
|||
<lang Forth> |
|||
\ Brute force search, optimized to search only within integer bounds surrounding target |
\ Brute force search, optimized to search only within integer bounds surrounding target |
||
\ Forth 200x compliant |
\ Forth 200x compliant |
||
Line 880: | Line 880: | ||
2.71828e 1000 RealToRational swap . . 1264 465 |
2.71828e 1000 RealToRational swap . . 1264 465 |
||
0.9054054e 100 RealToRational swap . . 67 74 |
0.9054054e 100 RealToRational swap . . 67 74 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Fortran}}== |
=={{header|Fortran}}== |
||
Line 887: | Line 887: | ||
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. |
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. < |
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. <syntaxhighlight lang="fortran"> MODULE PQ !Plays with some integer arithmetic. |
||
INTEGER MSG !Output unit number. |
INTEGER MSG !Output unit number. |
||
CONTAINS !One good routine. |
CONTAINS !One good routine. |
||
Line 983: | Line 983: | ||
CALL RATIONALISE(0.518518D0,"Two repeats, truncated.") |
CALL RATIONALISE(0.518518D0,"Two repeats, truncated.") |
||
CALL RATIONALISE(0.518519D0,"Two repeats, rounded.") |
CALL RATIONALISE(0.518519D0,"Two repeats, rounded.") |
||
END</ |
END</syntaxhighlight> |
||
Some examples. Each rational value is followed by X - P/Q. Notice that 0·(518) repeating, presented as 0·518518, is ''not'' correctly rounded. |
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 1,115: | Line 1,115: | ||
=={{header|FreeBASIC}}== |
=={{header|FreeBASIC}}== |
||
< |
<syntaxhighlight lang="freebasic">'' Written in FreeBASIC |
||
'' (no error checking, limited to 64-bit signed math) |
'' (no error checking, limited to 64-bit signed math) |
||
type number as longint |
type number as longint |
||
Line 1,176: | Line 1,176: | ||
if n = "" then exit do |
if n = "" then exit do |
||
print n & ":", parserational(n) |
print n & ":", parserational(n) |
||
loop</ |
loop</syntaxhighlight> |
||
=={{header|Fōrmulæ}}== |
=={{header|Fōrmulæ}}== |
||
Line 1,188: | Line 1,188: | ||
=={{header|Go}}== |
=={{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. |
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. |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 1,203: | Line 1,203: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 1,216: | Line 1,216: | ||
'''Test:''' |
'''Test:''' |
||
< |
<syntaxhighlight lang="groovy">Number.metaClass.mixin RationalCategory |
||
[ |
[ |
||
Line 1,222: | Line 1,222: | ||
].each{ |
].each{ |
||
printf "%30.27f %s\n", it, it as Rational |
printf "%30.27f %s\n", it, it as Rational |
||
}</ |
}</syntaxhighlight> |
||
'''Output:''' |
'''Output:''' |
||
Line 1,238: | Line 1,238: | ||
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. |
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. |
||
< |
<syntaxhighlight lang="haskell">Prelude> map (\d -> Ratio.approxRational d 0.0001) [0.9054054, 0.518518, 0.75] |
||
[67 % 74,14 % 27,3 % 4] |
[67 % 74,14 % 27,3 % 4] |
||
Prelude> [0.9054054, 0.518518, 0.75] :: [Rational] |
Prelude> [0.9054054, 0.518518, 0.75] :: [Rational] |
||
[4527027 % 5000000,259259 % 500000,3 % 4] |
[4527027 % 5000000,259259 % 500000,3 % 4] |
||
Prelude> map (fst . head . Numeric.readFloat) ["0.9054054", "0.518518", "0.75"] :: [Rational] |
Prelude> map (fst . head . Numeric.readFloat) ["0.9054054", "0.518518", "0.75"] :: [Rational] |
||
[4527027 % 5000000,259259 % 500000,3 % 4]</ |
[4527027 % 5000000,259259 % 500000,3 % 4]</syntaxhighlight> |
||
=={{header|J}}== |
=={{header|J}}== |
||
J's <code>x:</code> built-in will find a rational number which "best matches" a floating point number. |
J's <code>x:</code> built-in will find a rational number which "best matches" a floating point number. |
||
< |
<syntaxhighlight lang="j"> x: 0.9054054 0.518518 0.75 NB. find "exact" rational representation |
||
127424481939351r140737488355328 866492568306r1671094481399 3r4</ |
127424481939351r140737488355328 866492568306r1671094481399 3r4</syntaxhighlight> |
||
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".) |
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: |
Note that the concept of "best" has to do with the expected precision of the argument: |
||
< |
<syntaxhighlight lang="j"> x: 0.9 0.5 |
||
9r10 1r2 |
9r10 1r2 |
||
x: 0.9054 0.5185 |
x: 0.9054 0.5185 |
||
Line 1,265: | Line 1,265: | ||
67r74 14r27 |
67r74 14r27 |
||
x: 0.9054054054054054 0.5185185185185185 |
x: 0.9054054054054054 0.5185185185185185 |
||
67r74 14r27</ |
67r74 14r27</syntaxhighlight> |
||
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: |
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: |
||
< |
<syntaxhighlight lang="j"> x:(!. 5e_11) 0.9054054054 0.5185185185 |
||
67r74 14r27</ |
67r74 14r27</syntaxhighlight> |
||
(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.) |
(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,276: | Line 1,276: | ||
Here are some other alternatives for dealing with decimals and fractions: |
Here are some other alternatives for dealing with decimals and fractions: |
||
< |
<syntaxhighlight 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 |
0.9054054000 0.5185180000 0.7500000000 |
||
0j10": x:inv 67r74 42r81 3r4 NB. decimal representation (shown to 10 decimal places) |
0j10": x:inv 67r74 42r81 3r4 NB. decimal representation (shown to 10 decimal places) |
||
0.9054054054 0.5185185185 0.7500000000 |
0.9054054054 0.5185185185 0.7500000000 |
||
x: x:inv 67r74 42r81 3r4 NB. invertible |
x: x:inv 67r74 42r81 3r4 NB. invertible |
||
67r74 14r27 3r4</ |
67r74 14r27 3r4</syntaxhighlight> |
||
=={{header|Java}}== |
=={{header|Java}}== |
||
< |
<syntaxhighlight lang="java">import org.apache.commons.math3.fraction.BigFraction; |
||
public class Test { |
public class Test { |
||
Line 1,295: | Line 1,295: | ||
System.out.printf("%-12s : %s%n", d, new BigFraction(d, 0.00000002D, 10000)); |
System.out.printf("%-12s : %s%n", d, new BigFraction(d, 0.00000002D, 10000)); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
<pre>0.75 : 3 / 4 |
<pre>0.75 : 3 / 4 |
||
0.518518 : 37031 / 71417 |
0.518518 : 37031 / 71417 |
||
Line 1,307: | Line 1,307: | ||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |
||
Deriving an approximation within a specified tolerance: |
Deriving an approximation within a specified tolerance: |
||
< |
<syntaxhighlight lang="javascript">(() => { |
||
'use strict'; |
'use strict'; |
||
Line 1,355: | Line 1,355: | ||
// MAIN --- |
// MAIN --- |
||
return main(); |
return main(); |
||
})();</ |
})();</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>[ |
<pre>[ |
||
Line 1,378: | Line 1,378: | ||
(*) With the caveat that the C implementation of jq does not support unlimited-precision integer arithmetic. |
(*) 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 |
# Input: any JSON number, not only a decimal |
||
Line 1,406: | Line 1,406: | ||
| (.e | if length > 0 then tonumber else 0 end) as $e |
| (.e | if length > 0 then tonumber else 0 end) as $e |
||
| .s | dtor(null; $e) |
| .s | dtor(null; $e) |
||
end ;</ |
end ;</syntaxhighlight> |
||
'''Examples''' |
'''Examples''' |
||
< |
<syntaxhighlight lang="jq">0.9054054, |
||
0.518518, |
0.518518, |
||
0.75, |
0.75, |
||
1e308 |
1e308 |
||
| "\(.) → \(number_to_r | rpp)"</ |
| "\(.) → \(number_to_r | rpp)"</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,424: | Line 1,424: | ||
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. |
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. |
||
< |
<syntaxhighlight lang="julia">rationalize(0.9054054) |
||
rationalize(0.518518) |
rationalize(0.518518) |
||
rationalize(0.75)</ |
rationalize(0.75)</syntaxhighlight> |
||
4527027//5000000 |
4527027//5000000 |
||
Line 1,441: | Line 1,441: | ||
Here is the core algorithm written in Julia 1.0, without handling various data types and corner cases: |
Here is the core algorithm written in Julia 1.0, without handling various data types and corner cases: |
||
< |
<syntaxhighlight lang="julia">function rat(x::AbstractFloat, tol::Real=eps(x))::Rational |
||
p, q, pp, qq = copysign(1,x), 0, 0, 1 |
p, q, pp, qq = copysign(1,x), 0, 0, 1 |
||
x, y = abs(x), 1.0 |
x, y = abs(x), 1.0 |
||
Line 1,460: | Line 1,460: | ||
i = Int(cld(x-tt,y+t)) # find optimal semiconvergent: smallest i such that x-i*y < i*t+tt |
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) |
return (i*p+pp) // (i*q+qq) |
||
end</ |
end</syntaxhighlight> |
||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
< |
<syntaxhighlight lang="scala">// version 1.1.2 |
||
class Rational(val num: Long, val den: Long) { |
class Rational(val num: Long, val den: Long) { |
||
Line 1,491: | Line 1,491: | ||
for (decimal in decimals) |
for (decimal in decimals) |
||
println("${decimal.toString().padEnd(9)} = ${decimalToRational(decimal)}") |
println("${decimal.toString().padEnd(9)} = ${decimalToRational(decimal)}") |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,506: | Line 1,506: | ||
=={{header|Liberty BASIC}}== |
=={{header|Liberty BASIC}}== |
||
<syntaxhighlight lang="lb"> |
|||
<lang lb> |
|||
' Uses convention that one repeating sequence implies infinitely repeating sequence.. |
' Uses convention that one repeating sequence implies infinitely repeating sequence.. |
||
' Non-recurring fractions are limited to nd number of digits in nuerator & denominator |
' Non-recurring fractions are limited to nd number of digits in nuerator & denominator |
||
Line 1,582: | Line 1,582: | ||
if length /2 =int( length /2) then if mid$( i$, 3, length /2) =mid$( i$, 3 +length /2, length /2) then check$ ="recurring" |
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 |
end function |
||
</syntaxhighlight> |
|||
</lang> |
|||
<pre> |
<pre> |
||
0.5 is non-recurring |
0.5 is non-recurring |
||
Line 1,618: | Line 1,618: | ||
=={{header|Lua}}== |
=={{header|Lua}}== |
||
Brute force, and why not? |
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 |
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 |
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)) |
print(string.format("%15.13f --> %d / %d", v, n, d)) |
||
end</ |
end</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>0.9054054000000 --> 4527027 / 5000000 |
<pre>0.9054054000000 --> 4527027 / 5000000 |
||
Line 1,630: | Line 1,630: | ||
=={{header|Maple}}== |
=={{header|Maple}}== |
||
<syntaxhighlight lang="maple"> |
|||
<lang Maple> |
|||
> map( convert, [ 0.9054054, 0.518518, 0.75 ], 'rational', 'exact' ); |
> map( convert, [ 0.9054054, 0.518518, 0.75 ], 'rational', 'exact' ); |
||
4527027 259259 |
4527027 259259 |
||
[-------, ------, 3/4] |
[-------, ------, 3/4] |
||
5000000 500000 |
5000000 500000 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
||
< |
<syntaxhighlight lang="mathematica">Map[Rationalize[#,0]&,{0.9054054,0.518518, 0.75} ] |
||
-> {4527027/5000000,259259/500000,3/4}</ |
-> {4527027/5000000,259259/500000,3/4}</syntaxhighlight> |
||
=={{header|MATLAB}} / {{header|Octave}}== |
=={{header|MATLAB}} / {{header|Octave}}== |
||
<syntaxhighlight lang="matlab"> |
|||
<lang Matlab> |
|||
[a,b]=rat(.75) |
[a,b]=rat(.75) |
||
[a,b]=rat(.518518) |
[a,b]=rat(.518518) |
||
[a,b]=rat(.9054054) |
[a,b]=rat(.9054054) |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
Output: |
||
Line 1,665: | Line 1,665: | ||
{{improve|МК-61/52|This example is not clear, please improve it or delete it!}} |
{{improve|МК-61/52|This example is not clear, please improve it or delete it!}} |
||
<lang>П0 П1 ИП1 {x} x#0 14 КИП4 ИП1 1 0 |
<syntaxhighlight lang="text">П0 П1 ИП1 {x} x#0 14 КИП4 ИП1 1 0 |
||
* П1 БП 02 ИП4 10^x П0 ПA ИП1 ПB |
* П1 БП 02 ИП4 10^x П0 ПA ИП1 ПB |
||
ИПA ИПB / П9 КИП9 ИПA ИПB ПA ИП9 * |
ИПA ИПB / П9 КИП9 ИПA ИПB ПA ИП9 * |
||
- ПB x=0 20 ИПA ИП0 ИПA / П0 ИП1 |
- ПB x=0 20 ИПA ИП0 ИПA / П0 ИП1 |
||
ИПA / П1 ИП0 ИП1 С/П</ |
ИПA / П1 ИП0 ИП1 С/П</syntaxhighlight> |
||
=={{header|NetRexx}}== |
=={{header|NetRexx}}== |
||
Now the nearly equivalent program. |
Now the nearly equivalent program. |
||
< |
<syntaxhighlight lang="netrexx"> |
||
/*NetRexx program to convert decimal numbers to fractions ************* |
/*NetRexx program to convert decimal numbers to fractions ************* |
||
* 16.08.2012 Walter Pachl derived from Rexx Version 2 |
* 16.08.2012 Walter Pachl derived from Rexx Version 2 |
||
Line 1,734: | Line 1,734: | ||
end |
end |
||
If den=1 Then Return nom /* an integer */ |
If den=1 Then Return nom /* an integer */ |
||
Else Return nom'/'den /* otherwise a fraction */</ |
Else Return nom'/'den /* otherwise a fraction */</syntaxhighlight> |
||
Output is the same as for Rexx Version 2. |
Output is the same as for Rexx Version 2. |
||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
Similar to the Rust and Julia implementations. |
Similar to the Rust and Julia implementations. |
||
< |
<syntaxhighlight lang="nim">import math |
||
import fenv |
import fenv |
||
Line 1,794: | Line 1,794: | ||
echo rationalize(0.99) |
echo rationalize(0.99) |
||
echo rationalize(0.909) |
echo rationalize(0.909) |
||
echo rationalize(0.909, 0.001)</ |
echo rationalize(0.909, 0.001)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,814: | Line 1,814: | ||
Nim also has a rationals library for this, though it does not allow you to set tolerances like the code above. |
Nim also has a rationals library for this, though it does not allow you to set tolerances like the code above. |
||
< |
<syntaxhighlight lang="nim">import rationals |
||
echo toRational(0.9054054054) |
echo toRational(0.9054054054) |
||
Line 1,824: | Line 1,824: | ||
echo toRational(0.9) |
echo toRational(0.9) |
||
echo toRational(0.99) |
echo toRational(0.99) |
||
echo toRational(0.909)</ |
echo toRational(0.909)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,841: | Line 1,841: | ||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
Quick and dirty. |
Quick and dirty. |
||
< |
<syntaxhighlight lang="parigp">convert(x)={ |
||
my(n=0); |
my(n=0); |
||
while(x-floor(x*10^n)/10^n!=0.,n++); |
while(x-floor(x*10^n)/10^n!=0.,n++); |
||
floor(x*10^n)/10^n |
floor(x*10^n)/10^n |
||
};</ |
};</syntaxhighlight> |
||
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. |
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,851: | Line 1,851: | ||
=={{header|Perl}}== |
=={{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. |
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. |
||
< |
<syntaxhighlight lang="perl">sub gcd { |
||
my ($m, $n) = @_; |
my ($m, $n) = @_; |
||
($m, $n) = ($n, $m % $n) while $n; |
($m, $n) = ($n, $m % $n) while $n; |
||
Line 1,979: | Line 1,979: | ||
for (map { 10 ** $_ } 1 .. 10) { |
for (map { 10 ** $_ } 1 .. 10) { |
||
printf "approx below %g: %d / %d\n", $_, best_approx($x, $_) |
printf "approx below %g: %d / %d\n", $_, best_approx($x, $_) |
||
}</ |
}</syntaxhighlight> |
||
Output: <pre>3/8 = 0.375: |
Output: <pre>3/8 = 0.375: |
||
machine: 3/8 |
machine: 3/8 |
||
Line 2,015: | Line 2,015: | ||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
<!--< |
<!--<syntaxhighlight lang="phix">(phixonline)--> |
||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
||
<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> |
<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> |
||
Line 2,033: | Line 2,033: | ||
<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.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> |
<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}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,043: | Line 2,043: | ||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
{{works with|PHP|5.3+}} |
{{works with|PHP|5.3+}} |
||
< |
<syntaxhighlight lang="php">function asRational($val, $tolerance = 1.e-6) |
||
{ |
{ |
||
if ($val == (int) $val) { |
if ($val == (int) $val) { |
||
Line 2,074: | Line 2,074: | ||
echo asRational(1/4)."\n"; // "1/4" |
echo asRational(1/4)."\n"; // "1/4" |
||
echo asRational(1/3)."\n"; // "1/3" |
echo asRational(1/3)."\n"; // "1/3" |
||
echo asRational(5)."\n"; // "5"</ |
echo asRational(5)."\n"; // "5"</syntaxhighlight> |
||
=={{header|PL/I}}== |
=={{header|PL/I}}== |
||
<lang>(size, fofl): |
<syntaxhighlight lang="text">(size, fofl): |
||
Convert_Decimal_To_Rational: procedure options (main); /* 14 January 2014, from Ada */ |
Convert_Decimal_To_Rational: procedure options (main); /* 14 January 2014, from Ada */ |
||
Line 2,130: | Line 2,130: | ||
end; |
end; |
||
end; |
end; |
||
end Convert_Decimal_To_Rational;</ |
end Convert_Decimal_To_Rational;</syntaxhighlight> |
||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 2,147: | Line 2,147: | ||
=={{header|PureBasic}}== |
=={{header|PureBasic}}== |
||
< |
<syntaxhighlight lang="purebasic">Procedure.i ggT(a.i, b.i) |
||
Define t.i : If a < b : Swap a, b : EndIf |
Define t.i : If a < b : Swap a, b : EndIf |
||
While a%b : t=a : a=b : b=t%a : Wend : ProcedureReturn b |
While a%b : t=a : a=b : b=t%a : Wend : ProcedureReturn b |
||
Line 2,170: | Line 2,170: | ||
DataSection |
DataSection |
||
Data.d 0.9054054,0.518518,0.75,0.0 |
Data.d 0.9054054,0.518518,0.75,0.0 |
||
EndDataSection</ |
EndDataSection</syntaxhighlight> |
||
<pre> |
<pre> |
||
0.9054054 -> 4527027/5000000 |
0.9054054 -> 4527027/5000000 |
||
Line 2,182: | Line 2,182: | ||
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. |
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. |
||
< |
<syntaxhighlight lang="python">>>> from fractions import Fraction |
||
>>> for d in (0.9054054, 0.518518, 0.75): print(d, Fraction.from_float(d).limit_denominator(100)) |
>>> for d in (0.9054054, 0.518518, 0.75): print(d, Fraction.from_float(d).limit_denominator(100)) |
||
Line 2,193: | Line 2,193: | ||
0.518518 259259/500000 |
0.518518 259259/500000 |
||
0.75 3/4 |
0.75 3/4 |
||
>>> </ |
>>> </syntaxhighlight> |
||
Or, writing our own '''approxRatio''' function: |
Or, writing our own '''approxRatio''' function: |
||
{{Works with|Python|3.7}} |
{{Works with|Python|3.7}} |
||
< |
<syntaxhighlight lang="python">'''Approximate rationals from decimals''' |
||
from math import (floor, gcd) |
from math import (floor, gcd) |
||
Line 2,316: | Line 2,316: | ||
# MAIN --- |
# MAIN --- |
||
if __name__ == '__main__': |
if __name__ == '__main__': |
||
main()</ |
main()</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>Approximate rationals from decimals (epsilon of 1/10000): |
<pre>Approximate rationals from decimals (epsilon of 1/10000): |
||
Line 2,332: | Line 2,332: | ||
=={{header|R}}== |
=={{header|R}}== |
||
<syntaxhighlight lang="r"> |
|||
<lang R> |
|||
ratio<-function(decimal){ |
ratio<-function(decimal){ |
||
denominator=1 |
denominator=1 |
||
Line 2,342: | Line 2,342: | ||
return(str) |
return(str) |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{Out}} |
{{Out}} |
||
<pre> |
<pre> |
||
Line 2,357: | Line 2,357: | ||
Using the Quackery big number rational arithmetic library <code>bigrat.qky</code>. |
Using the Quackery big number rational arithmetic library <code>bigrat.qky</code>. |
||
< |
<syntaxhighlight lang="quackery">[ $ "bigrat.qky" loadfile ] now! |
||
[ dup echo$ |
[ dup echo$ |
||
Line 2,369: | Line 2,369: | ||
say "." cr ] is task ( $ --> ) |
say "." cr ] is task ( $ --> ) |
||
$ "0.9054054 0.518518 0.75" nest$ witheach task</ |
$ "0.9054054 0.518518 0.75" nest$ witheach task</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 2,380: | Line 2,380: | ||
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. |
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. |
They have some amount of inaccuracy, but i guess it can be tolerated. |
||
< |
<syntaxhighlight lang="racket">#lang racket |
||
(inexact->exact 0.75) ; -> 3/4 |
(inexact->exact 0.75) ; -> 3/4 |
||
Line 2,386: | Line 2,386: | ||
(exact->inexact 67/74) ; -> 0.9054054054054054 |
(exact->inexact 67/74) ; -> 0.9054054054054054 |
||
(inexact->exact 0.9054054054054054) ;-> 8155166892806033/9007199254740992</ |
(inexact->exact 0.9054054054054054) ;-> 8155166892806033/9007199254740992</syntaxhighlight> |
||
=={{header|Raku}}== |
=={{header|Raku}}== |
||
(formerly Perl 6) |
(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: |
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: |
||
<lang |
<syntaxhighlight lang="raku" line>say .nude.join('/') for 0.9054054, 0.518518, 0.75;</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>4527027/5000000 |
<pre>4527027/5000000 |
||
Line 2,397: | Line 2,397: | ||
3/4</pre> |
3/4</pre> |
||
However, if we want to take repeating decimals into account, then we can get a bit fancier. |
However, if we want to take repeating decimals into account, then we can get a bit fancier. |
||
<lang |
<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 ( $int, $dec ) = ( $n ~~ /^ (\d+) \. (\d+) $/ )».Str or die; |
||
Line 2,414: | Line 2,414: | ||
for @a -> [ $n, $d ] { |
for @a -> [ $n, $d ] { |
||
say "$n with $d repeating digits = ", decimal_to_fraction( $n, $d ); |
say "$n with $d repeating digits = ", decimal_to_fraction( $n, $d ); |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>0.9054 with 3 repeating digits = 67/74 |
<pre>0.9054 with 3 repeating digits = 67/74 |
||
Line 2,450: | Line 2,450: | ||
<br>REXX can support almost any number of decimal digits, but '''10''' was chosen for practicality for this task. |
<br>REXX can support almost any number of decimal digits, but '''10''' was chosen for practicality for this task. |
||
< |
<syntaxhighlight 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. */ |
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.*/ |
parse arg orig 1 n.1 "/" n.2; if n.2='' then n.2=1 /*get the fraction.*/ |
||
Line 2,476: | Line 2,476: | ||
end /*while*/ |
end /*while*/ |
||
if h==1 then return b /*don't return number ÷ by 1.*/ |
if h==1 then return b /*don't return number ÷ by 1.*/ |
||
return b'/'h /*proper or improper fraction. */</ |
return b'/'h /*proper or improper fraction. */</syntaxhighlight> |
||
'''output''' when using various inputs (which are displayed as part of the output): |
'''output''' when using various inputs (which are displayed as part of the output): |
||
<br>(Multiple runs are shown, outputs are separated by a blank line.) |
<br>(Multiple runs are shown, outputs are separated by a blank line.) |
||
Line 2,500: | Line 2,500: | ||
===version 2=== |
===version 2=== |
||
< |
<syntaxhighlight lang="rexx">/*REXX program to convert decimal numbers to fractions **************** |
||
* 15.08.2012 Walter Pachl derived from above for readability |
* 15.08.2012 Walter Pachl derived from above for readability |
||
* It took me time to understand :-) I need descriptive variable names |
* It took me time to understand :-) I need descriptive variable names |
||
Line 2,569: | Line 2,569: | ||
if den=1 then return nom /* denominator 1: integer */ |
if den=1 then return nom /* denominator 1: integer */ |
||
return nom'/'den /* otherwise a fraction */ |
return nom'/'den /* otherwise a fraction */ |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 2,598: | Line 2,598: | ||
===version 3=== |
===version 3=== |
||
< |
<syntaxhighlight lang="rexx">/* REXX --------------------------------------------------------------- |
||
* 13.02.2014 Walter Pachl |
* 13.02.2014 Walter Pachl |
||
* specify the number as xxx.yyy(pqr) pqr is the period |
* specify the number as xxx.yyy(pqr) pqr is the period |
||
Line 2,658: | Line 2,658: | ||
Parse Arg a,b |
Parse Arg a,b |
||
if b = 0 then return abs(a) |
if b = 0 then return abs(a) |
||
return GCD(b,a//b)</ |
return GCD(b,a//b)</syntaxhighlight> |
||
'''Output:''' |
'''Output:''' |
||
<pre>5.55555 = 111111/20000 ok |
<pre>5.55555 = 111111/20000 ok |
||
Line 2,681: | Line 2,681: | ||
This converts the string representation of the given values directly to fractions. |
This converts the string representation of the given values directly to fractions. |
||
< |
<syntaxhighlight lang="ruby">> '0.9054054 0.518518 0.75'.split.each { |d| puts "%s %s" % [d, Rational(d)] } |
||
0.9054054 4527027/5000000 |
0.9054054 4527027/5000000 |
||
0.518518 259259/500000 |
0.518518 259259/500000 |
||
0.75 3/4 |
0.75 3/4 |
||
=> ["0.9054054", "0.518518", "0.75"]</ |
=> ["0.9054054", "0.518518", "0.75"]</syntaxhighlight> |
||
This loop finds the simplest fractions within a given radius, because the floating-point representation is not exact. |
This loop finds the simplest fractions within a given radius, because the floating-point representation is not exact. |
||
< |
<syntaxhighlight lang="ruby">[0.9054054, 0.518518, 0.75].each { |f| puts "#{f} #{f.rationalize(0.0001)}" } |
||
# =>0.9054054 67/74 |
# =>0.9054054 67/74 |
||
# =>0.518518 14/27 |
# =>0.518518 14/27 |
||
# =>0.75 3/4 |
# =>0.75 3/4 |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{works with|Ruby|2.1.0+}} |
{{works with|Ruby|2.1.0+}} |
||
A suffix for integer and float literals was introduced: |
A suffix for integer and float literals was introduced: |
||
Line 2,706: | Line 2,706: | ||
=={{header|Rust}}== |
=={{header|Rust}}== |
||
<lang> |
<syntaxhighlight lang="text"> |
||
extern crate rand; |
extern crate rand; |
||
extern crate num; |
extern crate num; |
||
Line 2,765: | Line 2,765: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
First test the function with 1_000_000 random double floats : |
First test the function with 1_000_000 random double floats : |
||
<pre> |
<pre> |
||
Line 2,796: | Line 2,796: | ||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
{{Out}}Best seen running in your browser [https://scastie.scala-lang.org/rrlFnuTURgirBiTsH3Kqrg Scastie (remote JVM)]. |
{{Out}}Best seen running in your browser [https://scastie.scala-lang.org/rrlFnuTURgirBiTsH3Kqrg Scastie (remote JVM)]. |
||
< |
<syntaxhighlight lang="scala">import org.apache.commons.math3.fraction.BigFraction |
||
object Number2Fraction extends App { |
object Number2Fraction extends App { |
||
Line 2,803: | Line 2,803: | ||
for (d <- n) |
for (d <- n) |
||
println(f"$d%-12s : ${new BigFraction(d, 0.00000002D, 10000)}%s") |
println(f"$d%-12s : ${new BigFraction(d, 0.00000002D, 10000)}%s") |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Seed7}}== |
=={{header|Seed7}}== |
||
Line 2,809: | Line 2,809: | ||
defines the operator [http://seed7.sourceforge.net/libraries/bigrat.htm#%28attr_bigRational%29parse%28in_var_string%29 parse], |
defines the operator [http://seed7.sourceforge.net/libraries/bigrat.htm#%28attr_bigRational%29parse%28in_var_string%29 parse], |
||
which accepts, besides fractions, also a decimal number with repeating decimals. |
which accepts, besides fractions, also a decimal number with repeating decimals. |
||
< |
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i"; |
||
include "bigrat.s7i"; |
include "bigrat.s7i"; |
||
Line 2,827: | Line 2,827: | ||
writeln(bigRational parse "31.415926536"); |
writeln(bigRational parse "31.415926536"); |
||
writeln(bigRational parse "0.000000000"); |
writeln(bigRational parse "0.000000000"); |
||
end func;</ |
end func;</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>67/74 |
<pre>67/74 |
||
Line 2,845: | Line 2,845: | ||
=={{header|Sidef}}== |
=={{header|Sidef}}== |
||
By default, literal numbers are represented in rational form: |
By default, literal numbers are represented in rational form: |
||
< |
<syntaxhighlight lang="ruby">say 0.75.as_frac #=> 3/4 |
||
say 0.518518.as_frac #=> 259259/500000 |
say 0.518518.as_frac #=> 259259/500000 |
||
say 0.9054054.as_frac #=> 4527027/5000000</ |
say 0.9054054.as_frac #=> 4527027/5000000</syntaxhighlight> |
||
Additionally, '''Num(str)''' can be used for parsing a decimal expansion into rational form: |
Additionally, '''Num(str)''' can be used for parsing a decimal expansion into rational form: |
||
< |
<syntaxhighlight lang="ruby">'0.9054054 0.518518 0.75'.split.each { |str| |
||
say Num(str).as_frac |
say Num(str).as_frac |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 2,862: | Line 2,862: | ||
For rational approximations, the Number '''.rat_approx''' method can be used: |
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</ |
say 0.9054054.rat_approx.as_frac #=> 67/74</syntaxhighlight> |
||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
{{works with|Tcl|8.4+}} |
{{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: |
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: |
||
< |
<syntaxhighlight lang="tcl">#!/usr/bin/env tclsh |
||
proc dbl2frac {dbl {eps 0.000001}} { |
proc dbl2frac {dbl {eps 0.000001}} { |
||
Line 2,889: | Line 2,889: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
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: |
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 |
~ $ fractional.tcl |
||
Line 2,897: | Line 2,897: | ||
=={{header|Vala}}== |
=={{header|Vala}}== |
||
{{trans|C}} |
{{trans|C}} |
||
< |
<syntaxhighlight lang="vala">struct Fraction { |
||
public long d; |
public long d; |
||
public long n; |
public long n; |
||
Line 2,952: | Line 2,952: | ||
print("%11ld/%ld\n", r.n, r.d); |
print("%11ld/%ld\n", r.n, r.d); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 2,976: | Line 2,976: | ||
=={{header|VBA}}== |
=={{header|VBA}}== |
||
{{trans|D}} |
{{trans|D}} |
||
< |
<syntaxhighlight lang="vb">Function Real2Rational(r As Double, bound As Long) As String |
||
If r = 0 Then |
If r = 0 Then |
||
Line 3,055: | Line 3,055: | ||
Next i |
Next i |
||
End Sub |
End Sub |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 3,071: | Line 3,071: | ||
{{libheader|Wren-rat}} |
{{libheader|Wren-rat}} |
||
{{libheader|Wren-fmt}} |
{{libheader|Wren-fmt}} |
||
< |
<syntaxhighlight lang="ecmascript">import "/rat" for Rat |
||
import "/fmt" for Fmt |
import "/fmt" for Fmt |
||
Line 3,078: | Line 3,078: | ||
var r = Rat.fromFloat(test) |
var r = Rat.fromFloat(test) |
||
System.print("%(Fmt.s(-9, test)) -> %(r)") |
System.print("%(Fmt.s(-9, test)) -> %(r)") |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 3,089: | Line 3,089: | ||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
{{trans|D}} |
{{trans|D}} |
||
< |
<syntaxhighlight lang="zkl">fcn real2Rational(r,bound){ |
||
if (r == 0.0) return(0,1); |
if (r == 0.0) return(0,1); |
||
if (r < 0.0){ |
if (r < 0.0){ |
||
Line 3,102: | Line 3,102: | ||
return((r*best).round().toInt(),best); |
return((r*best).round().toInt(),best); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
< |
<syntaxhighlight lang="zkl">tests := T(0.750000000, 0.518518000, 0.905405400, |
||
0.142857143, 3.141592654, 2.718281828, |
0.142857143, 3.141592654, 2.718281828, |
||
-0.423310825, 31.415926536); |
-0.423310825, 31.415926536); |
||
Line 3,111: | Line 3,111: | ||
{ print(" %d/%d".fmt(real2Rational(r,(10).pow(i)).xplode())) } |
{ print(" %d/%d".fmt(real2Rational(r,(10).pow(i)).xplode())) } |
||
println(); |
println(); |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |