// 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 }
// 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 }