Engel expansion: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
(Added Quackery.)
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(12 intermediate revisions by 3 users not shown)
Line 156:
Engel expansion: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 33, 33, 35, 58, 62, 521, 3125] (34 components)
Back to rational: 25.628906
</pre>
 
=={{header|Maxima}}==
<syntaxhighlight lang="maxima">
engel_encode(x) := block (
[a:[]],
while(x > 0) do (
ai: ceiling(1/x),
x: x*ai - 1,
a: append(a, [ai])
),
return(a)
);
engel_decode(a) := block (
[x:0, my_product:1],
for ai in a do (
my_product: my_product*ai,
x: x + 1/(my_product)
),
return(x)
);
</syntaxhighlight>
{{out}}
<pre>
engel_encode(3.14159265358979);
[1,1,1,8,8,17,19,300,1991,2767,8641,16313,1628438,7702318,25297938,431350188,765676622,776491263,1739733589,2329473788,6871947674,17179869184]
engel_decode(%);
7074237752028433/2251799813685248
 
engel_encode(2.71828182845904);
[1,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,60,89,126,565,686,1293,7419,13529,59245,65443,133166,225384,655321,656924,2365071,2618883,5212339,107374183,178956971,536870912]
engel_decode(%);
3060513257434031/1125899906842624
 
engel_encode(1.414213562373095);
[1,3,5,5,16,18,78,102,120,144,277,286,740,38370,118617,120453,169594,5696244,6316129,10129640,67108864]
engel_decode(%);
1592262918131443/1125899906842624
</pre>
 
=={{header|Nim}}==
===Task===
We use the module “rationals” from the standard library which is limited to <code>int64</code> numerators and denominators. We had to define a conversion function from string to Rational as using the provided conversion function from float to Rational gave inaccurate results.
<syntaxhighlight lang="Nim">import std/[math, rationals, strutils]
 
type Fract = Rational[int64]
 
func engel(x: Fract): seq[Natural] =
## Return the Engel expansion of rational "x".
var u = x
while u.num != 0:
let a = ceil(u.den.float / u.num.float).toInt
result.add a
u = u * a - 1
 
func toRational(s: string): Fract =
## Convert the string representation of a real to a rational
## without using an intermediate float representation.
var num = 0i64
var den = 1i64
var i = 0
var c = s[0]
while c != '.':
num = 10 * num + ord(c) - ord('0')
inc i
c = s[i]
inc i
while i < s.len:
num = 10 * num + ord(s[i]) - ord('0')
den *= 10
inc i
result = num // den
 
 
for val in ["3.14159265358979", "2.71828182845904", "1.414213562373095"]:
let e = engel(val.toRational)
echo "Value: ", val
echo "Engel expansion: ", e.join(" ")
echo()
</syntaxhighlight>
 
{{out}}
<pre>Value: 3.14159265358979
Engel expansion: 1 1 1 8 8 17 19 300 1991 2768 4442 4830 10560 37132 107315 244141 651042 1953125
 
Value: 2.71828182845904
Engel expansion: 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 17 82 144 321 2289 9041 21083 474060 887785 976563 1953125
 
Value: 1.414213562373095
Engel expansion: 1 3 5 5 16 18 78 102 120 144 260 968 18531 46065 63005 65105 78125
</pre>
 
===Stretch task===
{{libheader|bignum}}
The package “bignum” provides a “Rat” type but lacks a function to convert the string representing a real number to a <code>Rat</code>.
<syntaxhighlight lang="Nim">import std/strutils
import bignum
 
func engel(x: Rat): seq[Int] =
## Return the Engel expansion of rational "x".
var u = x
while u.num != 0:
let a = (u.denom + u.num - 1) div u.num
result.add a
u = u * a - 1
 
func toRat(s: string): Rat =
## Convert the string representation of a real to a rational.
var num = newInt(0)
var den = newInt(1)
var i = 0
var c = s[0]
while c != '.':
num = 10 * num + ord(c) - ord('0')
inc i
c = s[i]
inc i
while i < s.len:
num = 10 * num + ord(s[i]) - ord('0')
den *= 10
inc i
result = newRat(num, den)
 
for val in ["3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211",
"2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642743",
"1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927558"]:
let e = engel(val.toRat)
echo "Value: ", val
echo "Engel expansion: ", e[0..29].join(" ")
echo "Number of terms: ", e.len
echo()
</syntaxhighlight>
 
{{out}}
<pre>Value: 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211
Engel expansion: 1 1 1 8 8 17 19 300 1991 2492 7236 10586 34588 63403 70637 1236467 5417668 5515697 5633167 7458122 9637848 9805775 41840855 58408380 213130873 424342175 2366457522 4109464489 21846713216 27803071890
Number of terms: 231
 
Value: 2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642743
Engel expansion: 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
Number of terms: 150
 
Value: 1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927558
Engel expansion: 1 3 5 5 16 18 78 102 120 144 251 363 1402 31169 88630 184655 259252 298770 4196070 38538874 616984563 1975413035 5345718057 27843871197 54516286513 334398528974 445879679626 495957494386 2450869042061 2629541150527
Number of terms: 185
</pre>
 
Line 382 ⟶ 527:
 
=={{header|Quackery}}==
 
Quackery uses bignum rationals and only generates approximations when the programmer deems it necessary, so loss of precision is not an issue.
 
<syntaxhighlight lang="Quackery"> [ $ "bigrat.qky" loadfile ] now!
Line 404 ⟶ 551:
2drop ] is engel->v ( [ --> n/d )
 
$ "3.14159265358979 2.71828182845904 1.414213562373095"
nest$
witheach
[ $->v drop
2dup 200 point$ echo$ cr
v->engel dup echo cr
dup engel->vwitheach 200 point$[ echo$ i if sp ] cr
cr ]engel->v
200 point$ echo$ cr
cr ]
 
$ "3.1415926535897932384626433832795028841971693993751058"
$ "209749445923078164062862089986280348253421170679821480" join
$ "865132823066470938446095505822317253594081284811174502" join
$ "841027019385211" " join
nested
$ "2.7182818284590452353602874713526624977572470936999595"
$ "7496696762772407663035354759457138217852516642743" " join
nested join
$ "1.4142135623730950488016887242096980785696718753769480"
$ "731766797379907324784621070388503875343276415727350138" join
$ "462309122970249248360558507372126441214970999358314132" join
$ "226659275055927558" join
nested join
witheach
[ $->v drop
2dup 200 point$ echo$ cr cr
v->engel engel->v
dup 20030 point$split echo$ crdrop
witheach [ echo i if sp ]
cr ]</syntaxhighlight>
say "... " cr cr
engel->v
200 point$ echo$ cr cr
cr ]</syntaxhighlight>
 
{{out}}
 
<pre>3.14159265358979
[ 1 1 1 8 8 17 19 300 1991 2768 4442 4830 10560 37132 107315 244141 651042 1953125 ]
3.14159265358979
 
2.71828182845904
[ 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 17 82 144 321 2289 9041 21083 474060 887785 976563 1953125 ]
2.71828182845904
 
1.414213562373095
[ 1 3 5 5 16 18 78 102 120 144 260 968 18531 46065 63005 65105 78125 ]
1.414213562373095
 
 
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211
 
1 1 1 8 8 17 19 300 1991 2492 7236 10586 34588 63403 70637 1236467 5417668 5515697 5633167 7458122 9637848 9805775 41840855 58408380 213130873 424342175 2366457522 4109464489 21846713216 27803071890...
 
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211
 
 
2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642743
 
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29...
 
2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642743
 
 
1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927558
 
1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927558
1 3 5 5 16 18 78 102 120 144 251 363 1402 31169 88630 184655 259252 298770 4196070 38538874 616984563 1975413035 5345718057 27843871197 54516286513 334398528974 445879679626 495957494386 2450869042061 2629541150527...
</pre>
 
1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927558</pre>
 
=={{header|Raku}}==
Line 519 ⟶ 683:
 
However, I've also limited the number of terms accumulated by the 'fromEngel' function to 70 which is just enough to reproduce the high precision rationals in decimal notation. To accumulate all the terms in a reasonable time would require the use of Wren-gmp which I've tried to avoid so the solution will run under Wren-CLI.
<syntaxhighlight lang="ecmascriptwren">import "./big" for BigRat
import "./fmt" for Fmt
 
9,476

edits