Update all new Tasks
This commit is contained in:
parent
00a190b0a6
commit
91df62d461
5697 changed files with 93386 additions and 804 deletions
16
Task/Convert-decimal-number-to-rational/00DESCRIPTION
Normal file
16
Task/Convert-decimal-number-to-rational/00DESCRIPTION
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
The task is to write a program to transform a decimal number into a fraction in lowest terms.
|
||||
|
||||
It is not always possible to do this exactly. For instance, while rational numbers can be converted to decimal representation, some of them need an infinite number of digits to be represented exactly in decimal form. Namely, [[wp:Repeating decimal|repeating decimals]] such as 1/3 = 0.333...
|
||||
|
||||
Because of this, the following fractions cannot be obtained (reliably) unless the language has some way of representing repeating decimals:
|
||||
* 67 / 74 = 0.9(054) = 0.9054054...
|
||||
* 14 / 27 = 0.(518) = 0.518518...
|
||||
|
||||
Acceptable output:
|
||||
|
||||
* 0.9054054 → 4527027 / 5000000
|
||||
* 0.518518 → 259259 / 500000
|
||||
|
||||
Finite decimals are of course no problem:
|
||||
|
||||
* 0.75 → 3 / 4
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
generic
|
||||
type Real is digits <>;
|
||||
procedure Real_To_Rational(R: Real;
|
||||
Bound: Positive;
|
||||
Nominator: out Integer;
|
||||
Denominator: out Positive);
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
procedure Real_To_Rational (R: Real;
|
||||
Bound: Positive;
|
||||
Nominator: out Integer;
|
||||
Denominator: out Positive) is
|
||||
Error: Real;
|
||||
Best: Positive := 1;
|
||||
Best_Error: Real := Real'Last;
|
||||
begin
|
||||
if R = 0.0 then
|
||||
Nominator := 0;
|
||||
Denominator := 1;
|
||||
return;
|
||||
elsif R < 0.0 then
|
||||
Real_To_Rational(-R, Bound, Nominator, Denominator);
|
||||
Nominator := - Nominator;
|
||||
return;
|
||||
else
|
||||
for I in 1 .. Bound loop
|
||||
Error := abs(Real(I) * R - Real'Rounding(Real(I) * R));
|
||||
if Error < Best_Error then
|
||||
Best := I;
|
||||
Best_Error := Error;
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
Denominator := Best;
|
||||
Nominator := Integer(Real'Rounding(Real(Denominator) * R));
|
||||
|
||||
end Real_To_Rational;
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
with Ada.Text_IO; With Real_To_Rational;
|
||||
|
||||
procedure Convert_Decimal_To_Rational is
|
||||
|
||||
type My_Real is new Long_Float; -- change this for another "Real" type
|
||||
|
||||
package FIO is new Ada.Text_IO.Float_IO(My_Real);
|
||||
procedure R2R is new Real_To_Rational(My_Real);
|
||||
|
||||
Nom, Denom: Integer;
|
||||
R: My_Real;
|
||||
|
||||
begin
|
||||
loop
|
||||
Ada.Text_IO.New_Line;
|
||||
FIO.Get(R);
|
||||
FIO.Put(R, Fore => 2, Aft => 9, Exp => 0);
|
||||
exit when R = 0.0;
|
||||
for I in 0 .. 4 loop
|
||||
R2R(R, 10**I, Nom, Denom);
|
||||
Ada.Text_IO.Put(" " & Integer'Image(Nom) &
|
||||
" /" & Integer'Image(Denom));
|
||||
end loop;
|
||||
end loop;
|
||||
end Convert_Decimal_To_Rational;
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
Array := []
|
||||
inputbox, string, Enter Number
|
||||
stringsplit, string, string, .
|
||||
if ( string1 = 0 )
|
||||
string1 =
|
||||
loop, parse, string, .
|
||||
if A_index = 2
|
||||
loop, parse, A_loopfield
|
||||
Array[A_index] := A_loopfield, k := A_index
|
||||
if (k = 1)
|
||||
{
|
||||
numerator := Array[1]
|
||||
Denominator := 10
|
||||
goto label
|
||||
}
|
||||
Original1 := K
|
||||
To_rn := floor(k/2)
|
||||
M_M := k - To_rn
|
||||
Original2 := k - To_rn
|
||||
loop
|
||||
{
|
||||
loop, % To_rn
|
||||
|
||||
{
|
||||
Check1 .= Array[k]
|
||||
Check2 .= Array[M_M]
|
||||
k--
|
||||
m_M--
|
||||
}
|
||||
if ( check1 = check2 )
|
||||
{
|
||||
;~ process beginsTO check;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
loop, % To_rn
|
||||
nines .= 9
|
||||
loop, % k - TO_rn
|
||||
Zeroes .= 0
|
||||
loop % k - TO_rn
|
||||
Minus .= Array[A_index]
|
||||
loop % k
|
||||
Plus .= Array[A_index]
|
||||
if ( minus = "" )
|
||||
minus := 0
|
||||
Numerator := Plus - minus
|
||||
Denominator := Nines . Zeroes
|
||||
;;;;;;;;;;;;;HCF
|
||||
goto, label
|
||||
}
|
||||
Check1 =
|
||||
check2 =
|
||||
k := Original1
|
||||
m_M := original2 + A_index
|
||||
TO_rn--
|
||||
if ( to_rn = 0 )
|
||||
{
|
||||
zeroes =
|
||||
loop % original1
|
||||
zeroes .= 0
|
||||
Denominator := 1 . zeroes
|
||||
numerator := string2
|
||||
goto, label
|
||||
}
|
||||
}
|
||||
esc::Exitapp
|
||||
label:
|
||||
Index := 2
|
||||
loop
|
||||
{
|
||||
|
||||
if (mod(denominator, numerator) = 0 )
|
||||
HCF := numerator
|
||||
if ( index = floor(numerator/2) )
|
||||
break
|
||||
if ( mod(numerator, index) = 0 ) && ( mod(denominator, index) = 0 )
|
||||
{
|
||||
HCF = %index%
|
||||
index++
|
||||
}
|
||||
else
|
||||
index++
|
||||
}
|
||||
if ( HCF = "" )
|
||||
Ans := numerator "/" Denominator
|
||||
else
|
||||
Ans := floor(numerator/HCF) "/" floor(Denominator/HCF)
|
||||
MsgBox % String . " -> " . String1 . " " . Ans
|
||||
reload
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
( ( exact
|
||||
= integerPart decimalPart z
|
||||
. @(!arg:?integerPart "." ?decimalPart)
|
||||
& !integerPart
|
||||
+ ( @( !decimalPart
|
||||
: (? ((%@:~0) ?:?decimalPart)) [?z
|
||||
)
|
||||
& !decimalPart*10^(-1*!z)
|
||||
| 0
|
||||
)
|
||||
| !arg
|
||||
)
|
||||
& ( approximation
|
||||
= integerPart firstDecimals repeatingDecimals
|
||||
, x y z z-y x-y numerator denominator
|
||||
. @( !arg
|
||||
: ?integerPart
|
||||
"."
|
||||
[?x
|
||||
?firstDecimals
|
||||
?repeatingDecimals
|
||||
[?y
|
||||
!repeatingDecimals
|
||||
[?z
|
||||
)
|
||||
& !z+-1*!y:?z-y
|
||||
& !x+-1*!y:?x-y
|
||||
& 10:?numerator:?denominator
|
||||
& ( !z-y:0&0:?repeatingDecimals
|
||||
| 9:?denominator
|
||||
& whl
|
||||
' ( !z+-1:>!y:?z
|
||||
& !numerator*10:?numerator
|
||||
& !denominator*10+9:?denominator
|
||||
)
|
||||
& @(!repeatingDecimals:? #?repeatingDecimals)
|
||||
)
|
||||
& ( @(!firstDecimals:? #?firstDecimals)
|
||||
| 0:?firstDecimals
|
||||
)
|
||||
& !integerPart
|
||||
+ !firstDecimals*10^(!x-y+!z-y)
|
||||
+ !numerator*!denominator^-1*!repeatingDecimals*10^!x-y
|
||||
)
|
||||
& "0.9054054054"
|
||||
"0.5185185185"
|
||||
"0.75"
|
||||
"0.905405400"
|
||||
"0.1428571428"
|
||||
"35.000"
|
||||
"35.001"
|
||||
"0.00000000001"
|
||||
"0.000001000001"
|
||||
"0.9"
|
||||
"0.99"
|
||||
"0.909"
|
||||
"0.9090"
|
||||
"0.90909"
|
||||
: ?decs
|
||||
& whl
|
||||
' ( !decs:%?dec ?decs
|
||||
& approximation$!dec:?approx
|
||||
& out
|
||||
$ ( !dec
|
||||
"="
|
||||
(exact$!dec:?precise)
|
||||
( !approx:!precise&
|
||||
| str$("(approx. " !approx ")")
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* f : number to convert.
|
||||
* num, denom: returned parts of the rational.
|
||||
* md: max denominator value. Note that machine floating point number
|
||||
* has a finite resolution (10e-16 ish for 64 bit double), so specifying
|
||||
* a "best match with minimal error" is often wrong, because one can
|
||||
* always just retrieve the significand and return that divided by
|
||||
* 2**52, which is in a sense accurate, but generally not very useful:
|
||||
* 1.0/7.0 would be "2573485501354569/18014398509481984", for example.
|
||||
*/
|
||||
void rat_approx(double f, int64_t md, int64_t *num, int64_t *denom)
|
||||
{
|
||||
/* a: continued fraction coefficients. */
|
||||
int64_t a, h[3] = { 0, 1, 0 }, k[3] = { 1, 0, 0 };
|
||||
int64_t x, d, n = 1;
|
||||
int i, neg = 0;
|
||||
|
||||
if (md <= 1) { *denom = 1; *num = (int64_t) f; return; }
|
||||
|
||||
if (f < 0) { neg = 1; f = -f; }
|
||||
|
||||
while (f != floor(f)) { n <<= 1; f *= 2; }
|
||||
d = f;
|
||||
|
||||
/* continued fraction and check denominator each step */
|
||||
for (i = 0; i < 64; i++) {
|
||||
a = n ? d / n : 0;
|
||||
if (i && !a) break;
|
||||
|
||||
x = d; d = n; n = x % n;
|
||||
|
||||
x = a;
|
||||
if (k[1] * a + k[0] >= md) {
|
||||
x = (md - k[0]) / k[1];
|
||||
if (x * 2 >= a || k[1] >= md)
|
||||
i = 65;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
h[2] = x * h[1] + h[0]; h[0] = h[1]; h[1] = h[2];
|
||||
k[2] = x * k[1] + k[0]; k[0] = k[1]; k[1] = k[2];
|
||||
}
|
||||
*denom = k[1];
|
||||
*num = neg ? -h[1] : h[1];
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int i;
|
||||
int64_t d, n;
|
||||
double f;
|
||||
|
||||
printf("f = %16.14f\n", f = 1.0/7);
|
||||
for (i = 1; i <= 20000000; i *= 16) {
|
||||
printf("denom <= %d: ", i);
|
||||
rat_approx(f, i, &n, &d);
|
||||
printf("%lld/%lld\n", n, d);
|
||||
}
|
||||
|
||||
printf("\nf = %16.14f\n", f = atan2(1,1) * 4);
|
||||
for (i = 1; i <= 20000000; i *= 16) {
|
||||
printf("denom <= %d: ", i);
|
||||
rat_approx(f, i, &n, &d);
|
||||
printf("%lld/%lld\n", n, d);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
f = 0.14285714285714
|
||||
denom <= 1: 0/1
|
||||
denom <= 16: 1/7
|
||||
denom <= 256: 1/7
|
||||
denom <= 4096: 1/7
|
||||
denom <= 65536: 1/7
|
||||
denom <= 1048576: 1/7
|
||||
denom <= 16777216: 1/7
|
||||
|
||||
f = 3.14159265358979
|
||||
denom <= 1: 3/1
|
||||
denom <= 16: 22/7
|
||||
denom <= 256: 355/113
|
||||
denom <= 4096: 355/113
|
||||
denom <= 65536: 104348/33215
|
||||
denom <= 1048576: 3126535/995207
|
||||
denom <= 16777216: 47627751/15160384
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
import std.stdio, std.math, std.string, std.typecons;
|
||||
|
||||
alias Fraction = Tuple!(int,"nominator", uint,"denominator");
|
||||
|
||||
Fraction real2Rational(in real r, in uint bound) /*pure*/ nothrow {
|
||||
if (r == 0.0) {
|
||||
return Fraction(0, 1);
|
||||
} else if (r < 0.0) {
|
||||
auto result = real2Rational(-r, bound);
|
||||
result.nominator = -result.nominator;
|
||||
return result;
|
||||
} else {
|
||||
uint best = 1;
|
||||
real bestError = real.max;
|
||||
|
||||
foreach (i; 1 .. bound + 1) {
|
||||
// round is not pure.
|
||||
immutable real error = abs(i * r - round(i * r));
|
||||
if (error < bestError) {
|
||||
best = i;
|
||||
bestError = error;
|
||||
}
|
||||
}
|
||||
|
||||
return Fraction(cast(int)round(best * r), best);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
immutable tests = [ 0.750000000, 0.518518000, 0.905405400,
|
||||
0.142857143, 3.141592654, 2.718281828,
|
||||
-0.423310825, 31.415926536];
|
||||
|
||||
foreach (r; tests) {
|
||||
writef("%8.9f ", r);
|
||||
foreach (i; 0 .. 5)
|
||||
writef(" %d/%d", real2Rational(r, 10 ^^ i).tupleof);
|
||||
writeln();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func main() {
|
||||
for _, d := range []string{"0.9054054", "0.518518", "0.75"} {
|
||||
if r, ok := new(big.Rat).SetString(d); ok {
|
||||
fmt.Println(d, "=", r)
|
||||
} else {
|
||||
fmt.Println(d, "invalid decimal number")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
Prelude> map (\d -> Ratio.approxRational d 0.0001) [0.9054054, 0.518518, 0.75]
|
||||
[67 % 74,14 % 27,3 % 4]
|
||||
Prelude> [0.9054054, 0.518518, 0.75] :: [Rational]
|
||||
[4527027 % 5000000,259259 % 500000,3 % 4]
|
||||
Prelude> map (fst . head . Numeric.readFloat) ["0.9054054", "0.518518", "0.75"] :: [Rational]
|
||||
[4527027 % 5000000,259259 % 500000,3 % 4]
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
x: 0.9054054 0.518518 0.75 NB. find "exact" rational representation
|
||||
127424481939351r140737488355328 866492568306r1671094481399 3r4
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
x: 0.9 0.5
|
||||
9r10 1r2
|
||||
x: 0.9054 0.5185
|
||||
4527r5000 1037r2000
|
||||
x: 0.9054054 0.5185185
|
||||
127424481939351r140737488355328 1037037r2000000
|
||||
x: 0.9054054054 0.5185185185
|
||||
5358191125333r5918002138463 6073341499873r11712872893031
|
||||
x: 0.9054054054054 0.5185185185185
|
||||
67r74 14r27
|
||||
x: 0.9054054054054054 0.5185185185185185
|
||||
67r74 14r27
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
x:(!. 5e_11) 0.9054054054 0.5185185185
|
||||
67r74 14r27
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
0j10": x:inv x: 0.9054054 0.518518 0.75 NB. invertible (shown to 10 decimal places)
|
||||
0.9054054000 0.5185180000 0.7500000000
|
||||
0j10": x:inv 67r74 42r81 3r4 NB. decimal representation (shown to 10 decimal places)
|
||||
0.9054054054 0.5185185185 0.7500000000
|
||||
x: x:inv 67r74 42r81 3r4 NB. invertible
|
||||
67r74 14r27 3r4
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
rational(0.9054054)
|
||||
rational(0.518518)
|
||||
rational(0.75)
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
' Uses convention that one repeating sequence implies infinitely repeating sequence..
|
||||
' Non-recurring fractions are limited to nd number of digits in nuerator & denominator
|
||||
|
||||
nd =3 ' suggest 3. 4 is slow. >4 is .......
|
||||
do
|
||||
read x$
|
||||
data "0.5", "0.1", "0.333", "1 /3", "0.33", "0.14159265", "2^-0.5", "0.1 +0.9*rnd(1)"
|
||||
data "0.142857142857", "int( 1000*rnd(1))/int( 1000*rnd(1))","end" ' always between 0 and 0.999999...
|
||||
if x$ ="end" then exit do
|
||||
print x$; " is ";
|
||||
type$ =check$( x$)
|
||||
print type$;
|
||||
|
||||
if type$ ="recurring" then
|
||||
x =val( mid$( x$, 3, ( len( x$) -2) /2))
|
||||
rep =( len( x$) -2) /2
|
||||
num =x
|
||||
den =10^rep -1
|
||||
gcd =gcd( num, den)
|
||||
print
|
||||
print " Calculating exact fraction for ", recurring$( x); " recurring & found";
|
||||
print num /gcd; " /"; den /gcd
|
||||
print
|
||||
else ' non-recurring. Check numerators & denominators <1000
|
||||
x =eval( x$)
|
||||
print
|
||||
print " Looking for fractions that are close to "; using( "#.############", x); " & found ";
|
||||
eps =10^nd
|
||||
for n = 1 to nd
|
||||
for i =1 to 10^n -1
|
||||
for j =i to 10^n -1
|
||||
fr =i /j
|
||||
if abs( x -fr) <eps then
|
||||
eps =abs( x -fr)
|
||||
'print i; " /"; j; " = ", using( "##.############", fr), "with error +/-"; using( "###.#########", eps /x *100); " %"
|
||||
ii =i: jj =j
|
||||
if eps =0 then exit for
|
||||
end if
|
||||
next j
|
||||
scan
|
||||
if eps =0 then exit for
|
||||
next i
|
||||
if eps =0 then exit for
|
||||
next n
|
||||
print ii; " /"; jj
|
||||
print
|
||||
end if
|
||||
loop until 0
|
||||
|
||||
print
|
||||
print "END."
|
||||
|
||||
end
|
||||
|
||||
function recurring$( x)
|
||||
recurring$ ="0."
|
||||
do
|
||||
recurring$ =recurring$ +str$( x)
|
||||
loop until len( recurring$) >=14
|
||||
end function
|
||||
|
||||
function gcd( a, b) ' thanks Uncle Ben..
|
||||
while b <>0
|
||||
t =b
|
||||
b =a mod b
|
||||
a =t
|
||||
wend
|
||||
gcd =a
|
||||
end function
|
||||
|
||||
function check$( i$)
|
||||
check$ ="non-recurring"
|
||||
length =len( i$) -2 ' allow for the '0.'.
|
||||
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
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
[a,b]=rat(.75)
|
||||
[a,b]=rat(.518518)
|
||||
[a,b]=rat(.9054054)
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
> map( convert, [ 0.9054054, 0.518518, 0.75 ], 'rational', 'exact' );
|
||||
4527027 259259
|
||||
[-------, ------, 3/4]
|
||||
5000000 500000
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
Map[Rationalize[#,0]&,{0.9054054,0.518518, 0.75} ]
|
||||
-> {4527027/5000000,259259/500000,3/4}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*NetRexx program to convert decimal numbers to fractions *************
|
||||
* 16.08.2012 Walter Pachl derived from Rexx Version 2
|
||||
**********************************************************************/
|
||||
options replace format comments java crossref savelog symbols
|
||||
Numeric Digits 10 /* use "only" 10 digs of precision */
|
||||
ratt('0.9054054054','67/74')
|
||||
ratt('0.5185185185','14/27')
|
||||
ratt('0.75' ,'3/4')
|
||||
ratt('0.905405400',' 693627417/766095958')
|
||||
ratt('0.9054054054','67/74')
|
||||
ratt('0.1428571428','1/7')
|
||||
ratt('35.000','35')
|
||||
ratt('35.001','35001/1000')
|
||||
ratt('0.00000000001','?')
|
||||
ratt('0.000001000001','1/999999')
|
||||
|
||||
ratt(0.9054054054,'1/3')
|
||||
|
||||
|
||||
method ratt(d = Rexx,fs = Rexx) public static
|
||||
fract=rat(d)
|
||||
Say ' 'd '->' fract
|
||||
Parse fract no '/' de
|
||||
If de='' Then x=no
|
||||
Else x=no/de
|
||||
If x<>d Then
|
||||
Say '> '||x 'is different'
|
||||
|
||||
method rat(in, high='') public static
|
||||
/**********************************************************************
|
||||
* rat(number<,high) returns a fraction or an integer that is equal to
|
||||
* or approximately equal to number.
|
||||
* Nominator and denominator must not have more than high digits
|
||||
* 16.08.2012 Walter Pachl derived from Rexx Version 2
|
||||
**********************************************************************/
|
||||
if high=='' then
|
||||
high=10**(digits - 1) /* maximum nominator/denominator */
|
||||
x=in /* working copy */
|
||||
nom=0 /* start values nominator */
|
||||
den=1 /* denominator */
|
||||
tnom=1 /* temp nominator */
|
||||
tden=0 /* temp denominator */
|
||||
loop While tnom<=high & tden<=high /* nominator... not too large */
|
||||
n=x.trunc() /* take integer part of x */
|
||||
z=tnom; /* save temp nominator */
|
||||
tnom=n*tnom+nom; /* compute new temp nominator */
|
||||
nom=z /* assign nominator */
|
||||
z=tden; /* save temp denominator */
|
||||
tden=n*tden+den /* compute new temp denominato*/
|
||||
den=z /* assign denominator */
|
||||
if n=x | tnom/tden=in then do
|
||||
if tnom>high | tden>high then /* temp value(s) too large */
|
||||
Leave /* don't use them */
|
||||
nom=tnom /* otherwise take them as */
|
||||
den=tden /* final values */
|
||||
leave /* and end the loop */
|
||||
end
|
||||
x=1/(x-n) /* compute x for next round */
|
||||
end
|
||||
If den=1 Then Return nom /* an integer */
|
||||
Else Return nom'/'den /* otherwise a fraction */
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
convert(x)={
|
||||
my(n=0);
|
||||
while(x-floor(x*10^n)/10^n!=0.,n++);
|
||||
floor(x*10^n)/10^n
|
||||
};
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
(size, fofl):
|
||||
Convert_Decimal_To_Rational: procedure options (main); /* 14 January 2014, from Ada */
|
||||
|
||||
Real_To_Rational: procedure (R, Bound, Numerator, Denominator) recursive
|
||||
options (reorder);
|
||||
declare R float (18), Bound float,
|
||||
(Numerator, Denominator) fixed binary (31);
|
||||
declare Error float;
|
||||
declare Best fixed binary initial (1);
|
||||
declare Best_Error float initial (huge(error));
|
||||
declare I fixed binary (31);
|
||||
|
||||
if R = 0 then
|
||||
do;
|
||||
Numerator = 0;
|
||||
Denominator = 1;
|
||||
return;
|
||||
end;
|
||||
else if R < 0 then
|
||||
do;
|
||||
call Real_To_Rational(-R, Bound, Numerator, Denominator);
|
||||
Numerator = -Numerator;
|
||||
return;
|
||||
end;
|
||||
else
|
||||
do I = 1 to Bound;
|
||||
Error = abs(I * R - trunc(I * R + sign(R)*0.5));
|
||||
if Error < Best_Error then
|
||||
do;
|
||||
Best = I;
|
||||
Best_Error = Error;
|
||||
end;
|
||||
end;
|
||||
|
||||
Denominator = Best;
|
||||
Numerator = Denominator * R + sign(R) * 0.5;
|
||||
|
||||
end Real_To_Rational;
|
||||
|
||||
|
||||
declare (Num, Denom) fixed binary (31);
|
||||
declare R float (18);
|
||||
declare I fixed BINARY;
|
||||
|
||||
do R = 0.75, 0.25, 0.3333333, 0.518518000, 0.905405400,
|
||||
0.142857143, 3.141592654, 2.718281828, -0.423310825,
|
||||
31.415926536, 0;
|
||||
put skip edit(R) (f(13,9));
|
||||
do I = 0 to 4;
|
||||
call Real_to_Rational(R, 10**I, Num, Denom);
|
||||
put edit(' ' || trim(Num) || ' / ' || trim(Denom)) (a);
|
||||
end;
|
||||
end;
|
||||
end Convert_Decimal_To_Rational;
|
||||
|
|
@ -0,0 +1 @@
|
|||
say .nude.join('/') for 0.9054054, 0.518518, 0.75;
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
sub decimal_to_fraction ( Str $n, Int $rep_digits = 0 ) returns Str {
|
||||
my ( $int, $dec ) = ( $n ~~ /^ (\d+) \. (\d+) $/ )».Str or die;
|
||||
|
||||
my ( $numer, $denom ) = ( $dec, 10 ** $dec.bytes );
|
||||
if $rep_digits {
|
||||
my $to_move = $dec.bytes - $rep_digits;
|
||||
$numer -= $dec.substr(0, $to_move);
|
||||
$denom -= 10 ** $to_move;
|
||||
}
|
||||
|
||||
my $rat = Rat.new( $numer.Int, $denom.Int ).perl;
|
||||
return $int ?? "$int $rat" !! $rat;
|
||||
}
|
||||
|
||||
my @a = ['0.9054', 3], ['0.518', 3], ['0.75', 0], (^4).map({['12.34567', $_]});
|
||||
for @a -> [ $n, $d ] {
|
||||
say "$n with $d repeating digits = ", decimal_to_fraction( $n, $d );
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
sub gcd {
|
||||
my ($m, $n) = @_;
|
||||
($m, $n) = ($n, $m % $n) while $n;
|
||||
return $m
|
||||
}
|
||||
|
||||
sub rat_machine {
|
||||
my $n = shift;
|
||||
my $denom = 1;
|
||||
while ($n != int $n) {
|
||||
# assuming the machine format is base 2, and multiplying
|
||||
# by 2 doesn't change the mantissa
|
||||
$n *= 2;
|
||||
|
||||
# multiply denom by 2, ignoring (very) possible overflow
|
||||
$denom <<= 1;
|
||||
}
|
||||
if ($n) {
|
||||
my $g = gcd($n, $denom);
|
||||
$n /= $g;
|
||||
$denom /= $g;
|
||||
}
|
||||
return $n, $denom;
|
||||
}
|
||||
|
||||
# helper, make continued fraction back into normal fraction
|
||||
sub get_denom {
|
||||
my ($num, $denom) = (1, pop @_);
|
||||
for (reverse @_) {
|
||||
($num, $denom) = ($denom, $_ * $denom + $num);
|
||||
}
|
||||
wantarray ? ($num, $denom) : $denom
|
||||
}
|
||||
|
||||
sub best_approx {
|
||||
my ($n, $limit) = @_;
|
||||
my ($denom, $neg);
|
||||
if ($n < 0) {
|
||||
$neg = 1;
|
||||
$n = -$n;
|
||||
}
|
||||
|
||||
my $int = int($n);
|
||||
my ($num, $denom, @coef) = (1, $n - $int);
|
||||
|
||||
# continued fraction, sort of
|
||||
while (1) {
|
||||
# make sure it terminates
|
||||
last if $limit * $denom < 1;
|
||||
my $i = int($num / $denom);
|
||||
|
||||
# not the right way to get limit, but it works
|
||||
push @coef, $i;
|
||||
|
||||
if (get_denom(@coef) > $limit) {
|
||||
pop @coef;
|
||||
last;
|
||||
}
|
||||
|
||||
# we lose precision here, but c'est la vie
|
||||
($num, $denom) = ($denom, $num - $i * $denom);
|
||||
}
|
||||
|
||||
($num, $denom) = get_denom @coef;
|
||||
$num += $denom * $int;
|
||||
|
||||
return $neg ? -$num : $num, $denom;
|
||||
}
|
||||
|
||||
sub rat_string {
|
||||
my $n = shift;
|
||||
my $denom = 1;
|
||||
my $neg;
|
||||
|
||||
# trival xyz.0000 ... case
|
||||
$n =~ s/\.0+$//;
|
||||
return $n, 1 unless $n =~ /\./;
|
||||
|
||||
if ($n =~ /^-/) {
|
||||
$neg = 1;
|
||||
$n =~ s/^-//;
|
||||
}
|
||||
|
||||
# shift decimal point to the right till it's gone
|
||||
$denom *= 10 while $n =~ s/\.(\d)/$1\./;
|
||||
$n =~ s/\.$//;
|
||||
|
||||
# removing leading zeros lest it looks like octal
|
||||
$n =~ s/^0*//;
|
||||
if ($n) {
|
||||
my $g = gcd($n, $denom);
|
||||
$n /= $g;
|
||||
$denom /= $g;
|
||||
}
|
||||
return $neg ? -$n : $n, $denom;
|
||||
}
|
||||
|
||||
my $limit = 1e8;
|
||||
my $x = 3/8;
|
||||
print "3/8 = $x:\n";
|
||||
printf "machine: %d/%d\n", rat_machine $x;
|
||||
printf "string: %d/%d\n", rat_string $x;
|
||||
printf "approx below $limit: %d/%d\n", best_approx $x, $limit;
|
||||
|
||||
$x = 137/4291;
|
||||
print "\n137/4291 = $x:\n";
|
||||
printf "machine: %d/%d\n", rat_machine $x;
|
||||
printf "string: %d/%d\n", rat_string $x;
|
||||
printf "approx below $limit: %d/%d\n", best_approx $x, $limit;
|
||||
|
||||
$x = sqrt(1/2);
|
||||
print "\n1/sqrt(2) = $x\n";
|
||||
printf "machine: %d/%d\n", rat_machine $x;
|
||||
printf "string: %d/%d\n", rat_string $x;
|
||||
printf "approx below 10: %d/%d\n", best_approx $x, 10;
|
||||
printf "approx below 100: %d/%d\n", best_approx $x, 100;
|
||||
printf "approx below 1000: %d/%d\n", best_approx $x, 1000;
|
||||
printf "approx below 10000: %d/%d\n", best_approx $x, 10000;
|
||||
printf "approx below 100000: %d/%d\n", best_approx $x, 100000;
|
||||
printf "approx below $limit: %d/%d\n", best_approx $x, $limit;
|
||||
|
||||
$x = -4 * atan2(1,1);
|
||||
print "\n-Pi = $x\n";
|
||||
printf "machine: %d/%d\n", rat_machine $x;
|
||||
printf "string: %d/%d\n", rat_string $x;
|
||||
|
||||
for (map { 10 ** $_ } 1 .. 10) {
|
||||
printf "approx below %g: %d / %d\n", $_, best_approx($x, $_)
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
>>> from fractions import Fraction
|
||||
>>> for d in (0.9054054, 0.518518, 0.75): print(d, Fraction.from_float(d).limit_denominator(100))
|
||||
|
||||
0.9054054 67/74
|
||||
0.518518 14/27
|
||||
0.75 3/4
|
||||
>>> for d in '0.9054054 0.518518 0.75'.split(): print(d, Fraction(d))
|
||||
|
||||
0.9054054 4527027/5000000
|
||||
0.518518 259259/500000
|
||||
0.75 3/4
|
||||
>>>
|
||||
1
Task/Convert-decimal-number-to-rational/README
Normal file
1
Task/Convert-decimal-number-to-rational/README
Normal file
|
|
@ -0,0 +1 @@
|
|||
Data source: http://rosettacode.org/wiki/Convert_decimal_number_to_rational
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/*REXX program converts a fraction [n/m] to it's simplest (lowest) terms*/
|
||||
numeric digits 10 /*use "only" 10 digs of precision*/
|
||||
parse arg orig 1 n.1 '/' n.2; if n.2='' then n.2=1
|
||||
if n.1='' then call er 'no argument specified.'
|
||||
do i=1 for 2 /*validate both args: n.1 n.2 */
|
||||
if \datatype(n.i,'N') then call er "argument isn't numeric:" n.i
|
||||
end /*i*/
|
||||
if n.2=0 then call er "divisor can't be zero." /*whoa, dividing by 0*/
|
||||
say 'old =' space(orig) /*display original. */
|
||||
say 'new =' rat(n.1/n.2) /*display the result.*/
|
||||
exit /*stick a fork in it, we're done.*/
|
||||
/*──────────────────────────────────ER subroutine───────────────────────*/
|
||||
er: say; say '***error!***'; say; say arg(1); say; exit 13
|
||||
/*──────────────────────────────────RAT subroutine──────────────────────*/
|
||||
rat: procedure; parse arg x 1 _x,y; if y=='' then y=10**(digits()-1)
|
||||
b=0; g=0; a=1; h=1 /*Y is the tolerance.*/
|
||||
do while a<=y & g<=y; n=trunc(_x)
|
||||
_=a; a=n*a+b; b=_
|
||||
_=g; g=n*g+h; h=_
|
||||
if n=_x | a/g=x then do
|
||||
if a>y | g>y then iterate
|
||||
b=a; h=g; leave
|
||||
end
|
||||
_x= 1 / (_x-n)
|
||||
end /*while a≤y & g≤y*/
|
||||
if h==1 then return b /*don't show number divided by 1 */
|
||||
return b'/'h /*show a proper|improper fraction*/
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*REXX program to convert decimal numbers to fractions ****************
|
||||
* 15.08.2012 Walter Pachl derived from above for readability
|
||||
* It took me time to understand :-) I need descriptive variable names
|
||||
* Output shows where the fraction only approximates the number
|
||||
* due to the limit (high) imposed on nominator and denominator
|
||||
**********************************************************************/
|
||||
Numeric Digits 10 /* use "only" 10 digs of precision */
|
||||
Call test '0.9054054054','67/74'
|
||||
Call test '0.5185185185','14/27'
|
||||
Call test '0.75' ,'3/4'
|
||||
Call test '0.905405400',' 693627417/766095958'
|
||||
Call test '0.9054054054','67/74'
|
||||
Call test '0.1428571428','1/7'
|
||||
Call test '35.000','35'
|
||||
Call test '35.001','35001/1000'
|
||||
Call test '0.00000000001','?'
|
||||
Call test '0.000001000001','1/999999'
|
||||
Exit
|
||||
|
||||
test:
|
||||
/**********************************************************************
|
||||
* Test driver for rat
|
||||
**********************************************************************/
|
||||
Parse Arg d,fs /* number and expected fraction */
|
||||
fh=rat(d) /* convert number to fracrion */
|
||||
Call o ' 'd fh
|
||||
If fh<>fs Then Call o ' not='fs
|
||||
interpret 'x='fh /* compute value of fraction */
|
||||
If x<>d Then /* not exactly equal to number */
|
||||
Call o '> '||x 'is different'
|
||||
Call o ' '
|
||||
Return
|
||||
|
||||
o: Say arg(1); Return
|
||||
|
||||
rat: procedure
|
||||
/**********************************************************************
|
||||
* rat(number<,high) returns a fraction or an integer that is equal to
|
||||
* or approximately equal to number.
|
||||
* Nominator and denominator must not have more than high digits
|
||||
* 15.08.2012 Walter Pachl derived from Version 1
|
||||
**********************************************************************/
|
||||
parse arg in,high
|
||||
x=in /* working copy */
|
||||
if high=='' then
|
||||
high=10**(digits()-1) /* maximum nominator/denominator */
|
||||
nom=0 /* start values nominator */
|
||||
den=1 /* denominator */
|
||||
tnom=1 /* temp nominator */
|
||||
tden=0 /* temp denominator */
|
||||
do While tnom<=high & tden<=high /* nominator... not too large */
|
||||
n=trunc(x) /* take integer part of x */
|
||||
z=tnom; /* save temp nominator */
|
||||
tnom=n*tnom+nom; /* compute new temp nominator */
|
||||
nom=z /* assign nominator */
|
||||
z=tden; /* save temp denominator */
|
||||
tden=n*tden+den /* compute new temp denominato*/
|
||||
den=z /* assign denominator */
|
||||
if n=x | tnom/tden=in then do
|
||||
if tnom>high | tden>high then /* temp value(s) too large */
|
||||
Leave /* don't use them */
|
||||
nom=tnom /* otherwise take them as */
|
||||
den=tden /* final values */
|
||||
leave /* and end the loop */
|
||||
end
|
||||
x=1/(x-n) /* compute x for next round */
|
||||
end
|
||||
if den=1 then return nom /* denominator 1: integer */
|
||||
return nom'/'den /* otherwise a fraction */
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/* REXX ---------------------------------------------------------------
|
||||
* 13.02.2014 Walter Pachl
|
||||
* specify the number as xxx.yyy(pqr) pqr is the period
|
||||
* for the number xxx.yyypqrpqrpqrpqrpqr...
|
||||
*--------------------------------------------------------------------*/
|
||||
Numeric Digits 100
|
||||
Call test '5.55555','111111/20000'
|
||||
Call test '3','3'
|
||||
Call test '0.03','3/100'
|
||||
Call test '0.9(054)','67/74'
|
||||
Call test '0.(3)','1/3'
|
||||
Call test '5.28(571428)','37/7'
|
||||
Call test '5.28(571428)','38/7 (demonstrate error case)'
|
||||
Call test '0.(518)','14/27'
|
||||
Call test '0.75' ,'3/4'
|
||||
Call test '0.(142857)','1/7'
|
||||
Call test '0.1(428571)','1/7'
|
||||
Call test '35.000','35'
|
||||
Call test '35.001','35001/1000'
|
||||
Call test '0.00000000001','1/100000000000'
|
||||
Call test '0.000001000001','1000001/1000000000000'
|
||||
Exit
|
||||
test:
|
||||
Parse Arg z, soll
|
||||
zin=z
|
||||
If pos('(',z)=0 Then Do
|
||||
Parse Var z i '.' f
|
||||
z=i||f
|
||||
n=10**length(f)
|
||||
End
|
||||
Else Do
|
||||
lp=pos('(',z)-3
|
||||
rp=pos(')',z)-4
|
||||
x=space(translate(z,' ','()'),0)
|
||||
z1=x*10**lp
|
||||
Parse Var z1 z1 '.'
|
||||
z2=x*10**rp
|
||||
z=z2-z1
|
||||
n=10**rp-10**lp
|
||||
End
|
||||
dd=gcd(z,n)
|
||||
zz=z/dd
|
||||
nn=n/dd
|
||||
If nn=1 Then
|
||||
fract=zz
|
||||
Else
|
||||
fract=zz'/'nn
|
||||
If fract==soll Then
|
||||
tag='ok'
|
||||
Else
|
||||
tag='should be' soll
|
||||
say zin '=' fract tag
|
||||
-- Say left(zz/nn,60)
|
||||
Return
|
||||
|
||||
GCD: procedure
|
||||
/**********************************************************************
|
||||
* Recursive procedure
|
||||
**********************************************************************/
|
||||
Parse Arg a,b
|
||||
if b = 0 then return abs(a)
|
||||
return GCD(b,a//b)
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
#lang racket
|
||||
|
||||
(inexact->exact 0.75) ; -> 3/4
|
||||
(exact->inexact 3/4) ; -> 0.75
|
||||
|
||||
(exact->inexact 67/74) ; -> 0.9054054054054054
|
||||
(inexact->exact 0.9054054054054054) ;-> 8155166892806033/9007199254740992
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
> '0.9054054 0.518518 0.75'.split.each { |d| puts "%s %s" % [d, Rational(d)] }
|
||||
0.9054054 4527027/5000000
|
||||
0.518518 259259/500000
|
||||
0.75 3/4
|
||||
=> ["0.9054054", "0.518518", "0.75"]
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
> [0.9054054, 0.518518, 0.75].each { |d| puts "%s %s" % [d, Rational(d).rationalize(0.0001)] }
|
||||
0.9054054 67/74
|
||||
0.518518 14/27
|
||||
0.75 3/4
|
||||
=> [0.9054054, 0.518518, 0.75]
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
$ include "seed7_05.s7i";
|
||||
include "bigrat.s7i";
|
||||
|
||||
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");
|
||||
end func;
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env tclsh
|
||||
|
||||
proc dbl2frac {dbl {eps 0.000001}} {
|
||||
for {set den 1} {$den<1024} {incr den} {
|
||||
set num [expr {round($dbl*$den)}]
|
||||
if {abs(double($num)/$den - $dbl) < $eps} break
|
||||
}
|
||||
list $num $den
|
||||
}
|
||||
#-------------------- That's all... the rest is the test suite
|
||||
if {[file tail $argv0] eq [file tail [info script]]} {
|
||||
foreach {test -> expected} {
|
||||
{dbl2frac 0.518518} -> {42 81}
|
||||
{dbl2frac 0.75} -> {3 4}
|
||||
{dbl2frac 0.9054054} -> {67 74}
|
||||
} {
|
||||
catch $test res
|
||||
if {$res ne $expected} {
|
||||
puts "$test -> $res, expected $expected"
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue