decimal/sqrt.go

36 lines
875 B
Go
Raw Normal View History

package decimal
const sqrtMaxIter = 10000
// Sqrt returns the square root of d, the result will have
// DivisionPrecision digits after the decimal point.
func (d Decimal) Sqrt() Decimal {
s, _ := d.SqrtRound(int32(DivisionPrecision))
return s
}
// SqrtRound returns the square root of d, the result will have
// precision digits after the decimal point. The bool precise returns whether the precision was reached
func (d Decimal) SqrtRound(precision int32) (Decimal, bool) {
2018-08-19 20:00:50 +02:00
if d.LessThanOrEqualZero() {
return Zero, false
}
cutoff := New(1, -precision)
lo := Zero
hi := d
var mid Decimal
for i := 0; i < sqrtMaxIter; i++ {
//mid = (lo+hi)/2;
mid = lo.Add(hi).DivRound(Two, precision)
if mid.Mul(mid).Sub(d).Abs().LessThan(cutoff) {
return mid, true
}
if mid.Mul(mid).GreaterThan(d) {
hi = mid
} else {
lo = mid
}
}
return mid, false
}