Skip to content

Commit 3279c0f

Browse files
author
shcabin
committed
add reference
1 parent 789db52 commit 3279c0f

File tree

2 files changed

+19
-14
lines changed

2 files changed

+19
-14
lines changed

lib.go

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -900,32 +900,36 @@ func floatToFraction(x float64, numeratorPlaceHolder, denominatorPlaceHolder int
900900

901901
// floatToFracUseContinuedFraction implement convert a floating-point decimal
902902
// to a fraction using continued fractions and recurrence relations.
903-
func floatToFracUseContinuedFraction(x float64, denominatorLimit int64) (num, den int64) {
904-
p_1 := int64(1)
905-
q_1 := int64(0)
906-
p_2 := int64(0)
907-
q_2 := int64(1)
903+
// Formula reference: https://en.wikipedia.org/wiki/Continued_fraction#Fundamental_recurrence_formulas
904+
// or https://oi-wiki.org/math/number-theory/continued-fraction/#%E9%80%92%E6%8E%A8%E5%85%B3%E7%B3%BB
905+
func floatToFracUseContinuedFraction(r float64, denominatorLimit int64) (num, den int64) {
906+
p_1 := int64(1) // LaTex: p_{-1}
907+
q_1 := int64(0) // LaTex: q_{-1}
908+
p_2 := int64(0) // LaTex: p_{-2}
909+
q_2 := int64(1) // LaTex: q_{-2}
908910
var lasta, lastb int64
909911
var curra, currb int64
910-
for i := 0; i < 100; i++ {
911-
a := int64(math.Floor(x))
912+
for k := 0; ; k++ {
913+
// a_{k} = \lfloor r_{k} \rfloor
914+
a := int64(math.Floor(r))
915+
// Fundamental recurrence formulas: p_{k} = a_{k} \cdot p_{k-1} + p_{k-2}
912916
curra, currb = a*p_1+p_2, a*q_1+q_2
913917
p_2 = p_1
914918
q_2 = q_1
915919
p_1 = curra
916920
q_1 = currb
917-
frac := x - float64(a)
921+
frac := r - float64(a)
918922
if q_1 >= denominatorLimit {
919-
return lasta, lastb //big.NewRat(lasta, lastb)
923+
return lasta, lastb
920924
}
921925
if math.Abs(frac) < 1e-12 {
922-
return curra, currb //big.NewRat(curra, currb)
926+
// use safe floating-point number comparison. If the input(r) is a real number, here is 0.
927+
return curra, currb
923928
}
924-
925929
lasta, lastb = curra, currb
926-
x = 1.0 / frac
930+
// r_{k+1} = \frac{1}{r_{k} - a_{k}}
931+
r = 1.0 / frac
927932
}
928-
return lasta, lastb //big.NewRat(lasta, lastb)
929933
}
930934

931935
// assignFieldValue assigns the value from an immutable reflect.Value to a

lib_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ func oldFractionHandler(frac float64, fracPlaceHolder int) string {
429429
}
430430

431431
func TestFloat2Frac(t *testing.T) {
432-
valueList := []float64{0.19, 0.54, 0.9, 0.99, 0.999, 0.999}
432+
valueList := []float64{0.19, 0.54, 0.9, 0.99, 0.999, 0.9999}
433433
for _, v := range valueList {
434434
for idx := 0; idx <= 10; idx++ {
435435
res1 := strings.Trim(oldFractionHandler(v, idx), " ")
@@ -448,4 +448,5 @@ func TestFloat2Frac(t *testing.T) {
448448
}
449449
}
450450
}
451+
assert.Equal(t, "954888175898973913/351283728530932463", floatToFraction(math.E, 1, 18))
451452
}

0 commit comments

Comments
 (0)