Continued fraction/Arithmetic/G(matrix ng, continued fraction n): Difference between revisions

→‎{{header|Go}}: Update Go to match other Continued_fraction/* tasks.
(→‎{{header|Go}}: Add Go solution)
(→‎{{header|Go}}: Update Go to match other Continued_fraction/* tasks.)
Line 176:
 
=={{header|Go}}==
<langAdding to the existing Go>package mainfrom the
[[Continued_fraction/Arithmetic/Construct_from_rational_number#Go]]
task, re-uses <code>cf.go</code> and <code>rat.go</code> as given in that task.
 
File <code>ng8.go</code>:
import (
<lang Go>package cf
"fmt"
"strings"
)
 
// A 2×2 matix:
type NextFn func() (term int64, more bool)
// [ a₁ a ]
type ContinuedFraction func() NextFn
// [ b₁ b ]
//
// which when "applied" to a continued fraction representing x
// gives a new continued fraction z such that:
//
// a₁ * x + a
// z = ----------
// b₁ * x + b
//
// Examples:
// NG4{0, 1, 0, 4}.ApplyTo(x) gives 0*x + 1/4 -> 1/4 = [0; 4]
// NG4{0, 1, 1, 0}.ApplyTo(x) gives 1/x
// NG4{1, 1, 0, 2}.ApplyTo(x) gives (x+1)/2
//
// Note that several operations (e.g. addition and division)
// can be efficiently done with a single matrix application.
// However, each matrix application may require
// several calculations for each outputed term.
type NG4 struct {
A1, A int64
B1, B int64
}
 
func (cfng ContinuedFractionNG4) StringneedsIngest() stringbool {
if ng.isDone() {
var buf strings.Builder
panic("b₁==b==0")
next := cf()
t, more := next()
fmt.Fprintf(&buf, "[%d", t)
sep := "; "
const maxTerms = 20
for n := 0; more; n++ {
if n > maxTerms {
fmt.Fprint(&buf, ", ...")
break
}
t, more = next()
fmt.Fprintf(&buf, "%s%d", sep, t)
sep = ", "
}
return ng.B1 == 0 || ng.B == 0 || ng.A1/ng.B1 != ng.A/ng.B
fmt.Fprint(&buf, "]")
return buf.String()
}
 
func (ng NG4) isDone() bool {
type NG4 [4]int64
return ng.B1 == 0 && ng.B == 0
 
func (ng NG4) needIngest() bool {
return ng[2] == 0 || ng[3] == 0 || ng[0]/ng[2] != ng[1]/ng[3]
}
func (ng NG4) done() bool {
return ng[2] == 0 && ng[3] == 0
}
 
Line 218 ⟶ 222:
// [ a₁ a ] becomes [ a + a₁×t a₁ ]
// [ b₁ b ] [ b + b₁×t b₁ ]
ng[0].A1, ng[1].A, ng[2].B1, ng[3].B =
ng[1].A+ng[0].A1*t, ng[0].A1,
ng[3].B+ng[2].B1*t, ng[2].B1
}
 
func (ng *NG4) ingestInfinite() {
// [ a₁ a ] becomes [ a₁ a₁ ]
// [ b₁ b ] [ b₁ b₁ ]
ng.A, ng.B = ng.A1, ng.B1
}
 
Line 226 ⟶ 236:
// [ a₁ a ] becomes [ b₁ b ]
// [ b₁ b ] [ a₁ - b₁×t a - b×t ]
ng[0].A1, ng[1].A, ng[2].B1, ng[3].B =
ng[2].B1, ng[3].B,
ng[0].A1-ng[2].B1*t, ng[1].A-ng[3].B*t
}
 
func (ng *NG4) ingestNone() {
// [ a₁ a ] becomes [ a₁ a₁ ]
// [ b₁ b ] [ b₁ b₁ ]
ng[1], ng[3] = ng[0], ng[2]
}
 
// ApplyTo "applies" the matrix `ng` to the continued fraction `cf`,
// returning the resulting continued fraction.
func (ng NG4) ApplyTo(cf ContinuedFraction) ContinuedFraction {
return ng4cf{ng,func() cf}.ApplyNextFn {
next := cf()
}
done := false
 
return func() (int64, bool) {
type ng4cf struct {
if done {
ng NG4
return 0, false
cf ContinuedFraction
}
 
func (g ng4cf) Apply() NextFn {
next := g.cf()
moreIn := true
return func() (t int64, more bool) {
for g.ng.needIngest() {
if g.ng.done() {
panic("b₁==b==0")
}
iffor moreInng.needsIngest() {
if t, moreInok := next(); ok {
g. ng.ingest(t)
} else {
g. ng.ingestNoneingestInfinite()
}
}
t := ng.A1 / ng.B1
ng.egest(t)
done = ng.isDone()
return t, true
}
t = g.ng[0] / g.ng[2]
g.ng.egest(t)
return t, moreIn || !g.ng.done()
}
}</lang>
}
File <code>ng4_test.go</code>:
<lang Go>package cf
 
import (
type Rat struct {
"fmt"
N, D int64
"reflect"
}
"testing"
)
 
func Example_NG4(r Rat) String() string {
return fmt.Sprintf("%d/%d", r.N, r.D)
}
 
func (r Rat) AsContinuedFraction() ContinuedFraction { return r.CFTerms }
func (r Rat) CFTerms() NextFn {
n, d := r.N, r.D
return func() (int64, bool) {
q := n / d
n, d = d, n-q*d
return q, d != 0
}
}
 
func Sqrt2() NextFn {
first := true
return func() (int64, bool) {
if first {
first = false
return 1, true
}
return 2, true
}
}
 
func main() {
cases := [...]struct {
r Rat
Line 307 ⟶ 285:
for _, tc := range cases {
cf := tc.r.AsContinuedFraction()
fmt.Printf("%5s = %-9s with %v gives %sv\n", tc.r, cf.String(), tc.ng,
tc.ng.ApplyTo(cf),
)
Line 316 ⟶ 294:
result := NG4{1, 1, 0, 2}.ApplyTo(Sqrt2)
fmt.Println("(1+√2)/2 =", result)
 
// Output:
// 13/11 = [1; 5, 2] with {2 1 0 2} gives [1; 1, 2, 7]
// 22/7 = [3; 7] with {2 1 0 2} gives [3; 1, 1, 1, 4]
// 22/7 = [3; 7] with {1 0 0 4} gives [0; 1, 3, 1, 2]
// 1/√2 = [0; 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ...]
// (1+√2)/2 = [1; 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, ...]
}</lang>
{{out}}
<pre>
13/11 = [1; 5, 2] with [{2 1 0 2]} gives [1; 1, 2, 7]
22/7 = [3; 7] with [{2 1 0 2]} gives [3; 1, 1, 1, 4]
22/7 = [3; 7] with [{1 0 0 4]} gives [0; 1, 3, 1, 2]
1/√2 = [0; 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ...]
(1+√2)/2 = [1; 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, ...]
</pre>
 
Anonymous user