Exemplo n.º 1
0
// QuadToString returns the string representation of a Quad number.
// It calls the C function QuadToString of the original decNumber package.
//
//       This function uses exponential notation quite often.
//       E.g. 0.0000001 returns "1E-7", which is often not what we want.
//
//       It is better to use the method AppendQuad() or String(), which don't use exponential notation for a wider range.
//       AppendQuad() and String() write a number without exp notation if it can be displayed with at most 34 digits, and an optional fractional point.
//
// The status field of a is not checked.
// If you need to check the status of a, you can call a.Error().
//
func (a Quad) QuadToString() string {
	var (
		retStr   C.Ret_str
		strSlice []byte // capacity must be exactly DecquadString
		s        string
	)

	retStr = C.mdq_QuadToString(a.val) // may use exponent notation

	strSlice = pool.Get().([]byte)[:DecquadString]
	defer pool.Put(strSlice)

	for i := 0; i < int(retStr.length); i++ {
		strSlice[i] = byte(retStr.s[i])
	}

	s = string(strSlice[:retStr.length])

	return s
}
Exemplo n.º 2
0
// AppendQuad appends string representation of Quad into byte slice.
// AppendQuad and String are best to display Quad, as exponent notation is used less often than with QuadToString.
//
//       AppendQuad() writes a number without exp notation if it can be displayed with at most 34 digits, and an optional fractional point.
//       Else, falls back on QuadToString(), which will use exponential notation.
//
// See also method String(), which calls AppendQuad internally.
//
// The status field of a is not checked.
// If you need to check the status of a, you can call a.Error().
//
func AppendQuad(dst []byte, a Quad) []byte {
	var (
		retStr   C.Ret_str
		strSlice []byte // length must be exactly DecquadString

		ret             C.Ret_BCD
		d               byte
		skipLeadingZero bool = true
		inf_nan         uint32
		exp             int32
		sign            uint32
		BCDslice        []byte // length must be exactly DecquadPmax

		buff [DecquadString]byte // enough for      sign    optional "0."    34 digits
	)

	// fill BCD array

	ret = C.mdq_to_BCD(a.val) // sign will be 1 for negative and non-zero number, else, 0. If Inf or Nan, returns an error.

	BCDslice = pool.Get().([]byte)[:DecquadPmax]
	defer pool.Put(BCDslice)

	for i := 0; i < DecquadPmax; i++ {
		BCDslice[i] = byte(ret.BCD[i])
	}
	inf_nan = uint32(ret.inf_nan)
	exp = int32(ret.exp)
	sign = uint32(ret.sign)

	// if Quad value is not in 34 digits range, or Inf or Nan, we want our function to output the number, or Infinity, or NaN. Falls back on QuadToString.

	if exp > 0 || exp < -DecquadPmax || inf_nan != 0 {
		retStr = C.mdq_QuadToString(a.val) // may use exponent notation

		strSlice = pool.Get().([]byte)[:DecquadString]
		defer pool.Put(strSlice)

		for i := 0; i < int(retStr.length); i++ {
			strSlice[i] = byte(retStr.s[i])
		}

		dst = append(dst, strSlice[:retStr.length]...) // write buff into destination and return

		return dst
	}

	// write string. Here, the number is not Inf nor Nan.

	i := 0

	integralPartLength := len(BCDslice) + int(exp) // here, exp is [-DecquadPmax ... 0]

	BCDintegralPart := BCDslice[:integralPartLength]
	BCDfractionalPart := BCDslice[integralPartLength:]

	for _, d = range BCDintegralPart { // ==== write integral part ====
		if skipLeadingZero && d == 0 {
			continue
		} else {
			skipLeadingZero = false
		}
		buff[i] = '0' + d
		i++
	}

	if i == 0 { // write '0' if no digit written for integral part
		buff[i] = '0'
		i++
	}

	if sign != 0 {
		dst = append(dst, '-') // write '-' sign if any into destination
	}

	dst = append(dst, buff[:i]...) // write integral part into destination

	if exp == 0 { // if no fractional part, just return
		return dst
	}

	dst = append(dst, '.') // ==== write fractional part ====

	i = 0
	for _, d = range BCDfractionalPart {
		buff[i] = '0' + d
		i++
	}

	dst = append(dst, buff[:i]...) // write fractional part into destination

	return dst
}