@@ -856,28 +856,53 @@ func bstrMarshal(s string) (result string) {
856856 return result
857857}
858858
859- // newRat converts decimals to rational fractions with the required precision.
860- func newRat (n float64 , iterations int64 , prec float64 ) * big.Rat {
861- x := int64 (math .Floor (n ))
862- y := n - float64 (x )
863- rat := continuedFraction (y , 1 , iterations , prec )
864- return rat .Add (rat , new (big.Rat ).SetInt64 (x ))
865- }
866-
867- // continuedFraction returns rational from decimal with the continued fraction
868- // algorithm.
869- func continuedFraction (n float64 , i int64 , limit int64 , prec float64 ) * big.Rat {
870- if i >= limit || n <= prec {
871- return big .NewRat (0 , 1 )
872- }
873- inverted := 1 / n
874- y := int64 (math .Floor (inverted ))
875- x := inverted - float64 (y )
876- ratY := new (big.Rat ).SetInt64 (y )
877- ratNext := continuedFraction (x , i + 1 , limit , prec )
878- res := ratY .Add (ratY , ratNext )
879- res = res .Inv (res )
880- return res
859+ // floatToFraction converts a float number to a fraction string representation
860+ // with specified placeholder widths for numerator and denominator.
861+ func floatToFraction (x float64 , numeratorPlaceHolder , denominatorPlaceHolder int ) string {
862+ if denominatorPlaceHolder <= 0 {
863+ return ""
864+ }
865+ num , den := floatToFracUseContinuedFraction (x , int64 (math .Pow10 (denominatorPlaceHolder )))
866+ if num == 0 {
867+ return strings .Repeat (" " , numeratorPlaceHolder + denominatorPlaceHolder + 1 )
868+ }
869+ numStr := strconv .FormatInt (num , 10 )
870+ denStr := strconv .FormatInt (den , 10 )
871+ numeratorPlaceHolder = max (numeratorPlaceHolder - len (numStr ), 0 )
872+ denominatorPlaceHolder = max (denominatorPlaceHolder - len (denStr ), 0 )
873+ return fmt .Sprintf ("%s%s/%s%s" , strings .Repeat (" " , numeratorPlaceHolder ), numStr , denStr , strings .Repeat (" " , denominatorPlaceHolder ))
874+ }
875+
876+ // floatToFracUseContinuedFraction implement convert a floating-point decimal
877+ // to a fraction using continued fractions and recurrence relations.
878+ func floatToFracUseContinuedFraction (r float64 , denominatorLimit int64 ) (num , den int64 ) {
879+ p_1 := int64 (1 ) // LaTex: p_{-1}
880+ q_1 := int64 (0 ) // LaTex: q_{-1}
881+ p_2 := int64 (0 ) // LaTex: p_{-2}
882+ q_2 := int64 (1 ) // LaTex: q_{-2}
883+ var lasta , lastb int64
884+ var curra , currb int64
885+ for k := 0 ; ; k ++ {
886+ // a_{k} = \lfloor r_{k} \rfloor
887+ a := int64 (math .Floor (r ))
888+ // Fundamental recurrence formulas: p_{k} = a_{k} \cdot p_{k-1} + p_{k-2}
889+ curra , currb = a * p_1 + p_2 , a * q_1 + q_2
890+ p_2 = p_1
891+ q_2 = q_1
892+ p_1 = curra
893+ q_1 = currb
894+ frac := r - float64 (a )
895+ if q_1 >= denominatorLimit {
896+ return lasta , lastb
897+ }
898+ if math .Abs (frac ) < 1e-12 {
899+ // use safe floating-point number comparison. If the input(r) is a real number, here is 0.
900+ return curra , currb
901+ }
902+ lasta , lastb = curra , currb
903+ // r_{k+1} = \frac{1}{r_{k} - a_{k}}
904+ r = 1.0 / frac
905+ }
881906}
882907
883908// assignFieldValue assigns the value from an immutable reflect.Value to a
0 commit comments