コード例 #1
0
ファイル: decimal.go プロジェクト: EricLagergren/decimal
// BitLen returns the absolute value of x in bits.
func (x *Big) BitLen() int {
	// If using an artificially inflated number determine the
	// bitlen using the number of digits.
	//
	// http://www.exploringbinary.com/number-of-bits-in-a-decimal-integer/
	if x.scale < 0 {
		// Number of zeros in scale + digits in z.
		d := -int(x.scale) + x.Prec()
		return int(math.Ceil(float64(d-1) * ln210))
	}
	if x.isCompact() {
		return arith.BitLen(x.compact)
	}
	return x.mantissa.BitLen()
}
コード例 #2
0
ファイル: decimal.go プロジェクト: EricLagergren/decimal
// Sqrt sets z to the square root of x and returns z.
// The precision of Sqrt is determined by z's Context.
// Sqrt will panic on negative values since Big cannot
// represent imaginary numbers.
func (z *Big) Sqrt(x *Big) *Big {
	if x.SignBit() {
		panic("math.Sqrt: cannot take square root of negative number")
	}

	switch {
	case x.form == inf:
		z.form = inf
		return z
	case x.Sign() == 0:
		z.form = zero
		return z
	}

	// First fast path---check if x is a perfect square. If it is, we can avoid
	// having to inflate x and can possibly use can use the hardware SQRT.
	// Note that we can only catch perfect squares that aren't big.Ints.
	if sq, ok := perfectSquare(x); ok {
		z.ctx = x.ctx
		return z.SetMantScale(sq, 0)
	}

	zp := z.ctx.prec()

	// Temporary inflation. Should be enough to accurately determine the sqrt
	// with at least zp digits after the radix.
	zpadj := int(zp) << 1

	var tmp *Big
	if z != x {
		zctx := z.ctx
		tmp = z.Set(x)
		tmp.ctx = zctx
	} else {
		tmp = new(Big).Set(x)
	}
	if !shiftRadixRight(tmp, zpadj) {
		z.form = inf
		return z
	}

	// Second fast path. Check to see if we can calculate the square root without
	// using big.Int
	if !x.IsBig() && zpadj <= 19 {
		n := tmp.Int64()
		ix := n >> uint((arith.BitLen(n)+1)>>1)
		var p int64
		for {
			p = ix
			ix += n / ix
			ix >>= 1
			if ix == p {
				return z.SetMantScale(ix, zp)
			}
		}
	}

	// x isn't a perfect square or x is a big.Int

	n := tmp.Int()
	ix := new(big.Int).Rsh(n, uint((n.BitLen()+1)>>1))

	var a, p big.Int
	for {
		p.Set(ix)
		ix.Add(ix, a.Quo(n, ix)).Rsh(ix, 1)
		if ix.Cmp(&p) == 0 {
			return z.SetBigMantScale(ix, zp)
		}
	}
}