-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rat.go
69 lines (61 loc) · 1.33 KB
/
rat.go
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package x
import (
"math/big"
)
var (
zeroInt = big.NewInt(0) //nolint:gochecknoglobals
oneInt = big.NewInt(1) //nolint:gochecknoglobals
twoInt = big.NewInt(2) //nolint:mnd,gochecknoglobals
fiveInt = big.NewInt(5) //nolint:mnd,gochecknoglobals
tenInt = big.NewInt(10) //nolint:mnd,gochecknoglobals
)
// RatPrecision computes for rat the number of non-repeating digits on the right
// of the decimal point and the number of repeating digits which cyclicly follow.
//
// It can be used with Rat.FloatString to convert a number to full precision
// representation, when there are no repeating digits.
//
// This is similar to Rat.FloatPrec but returns also the number of repeating digits
// following the non-repeating digits. Rat.FloatPrec is also much faster.
func RatPrecision(rat *big.Rat) (int, int) {
// Go assures that rat is normalized.
m := new(big.Int).Set(rat.Denom())
q := new(big.Int)
r := new(big.Int)
k := 0
for {
q.QuoRem(m, twoInt, r)
if r.Cmp(zeroInt) == 0 {
m, q = q, m
k++
} else {
break
}
}
l := 0
for {
q.QuoRem(m, fiveInt, r)
if r.Cmp(zeroInt) == 0 {
m, q = q, m
l++
} else {
break
}
}
j := 0
if m.Cmp(oneInt) != 0 {
q.SetInt64(1)
for {
q.Mul(q, tenInt)
q.Mod(q, m)
j++
if q.Cmp(oneInt) == 0 {
break
}
}
}
if k > l {
return k, j
}
return l, j
}