// 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. // // Zero values are signed (unlike AppendQuad and String methods): // -0 --> "-0" // -0.00 --> "-0.00" // // Displaying "-0" is often surprising for the user. That's why AppendQuad and String methods always discard the sign of zero values. // func (a Quad) QuadToString() string { var ( ret_str C.Ret_str str_slice []byte // capacity must be exactly DecquadString s string ) ret_str = C.mdq_to_QuadToString(a.val) // may use exponent notation str_slice = pool.Get().([]byte)[:DecquadString] defer pool.Put(str_slice) for i := 0; i < int(ret_str.length); i++ { str_slice[i] = byte(ret_str.s[i]) } s = string(str_slice[:ret_str.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. // // Zero values are always positive (unlike QuadToString method): // -0 --> "0" // -0.00 --> "0.00" // func AppendQuad(dst []byte, a Quad) []byte { var ( ret_str C.Ret_str str_slice []byte // length must be exactly DecquadString ret C.Ret_BCD d byte skip_leading_zero bool = true inf_nan uint32 exp int32 sign uint32 BCD_slice []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. BCD_slice = pool.Get().([]byte)[:DecquadPmax] defer pool.Put(BCD_slice) for i := 0; i < DecquadPmax; i++ { BCD_slice[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 { ret_str = C.mdq_to_QuadToString(a.val) // may use exponent notation str_slice = pool.Get().([]byte)[:DecquadString] defer pool.Put(str_slice) for i := 0; i < int(ret_str.length); i++ { str_slice[i] = byte(ret_str.s[i]) } dst = append(dst, str_slice[:ret_str.length]...) // write buff into destination and return return dst } // write string. Here, the number is not Inf nor Nan. i := 0 integral_part_length := len(BCD_slice) + int(exp) // here, exp is [-DecquadPmax ... 0] BCD_integral_part := BCD_slice[:integral_part_length] BCD_fractional_part := BCD_slice[integral_part_length:] for _, d = range BCD_integral_part { // ==== write integral part ==== if skip_leading_zero && d == 0 { continue } else { skip_leading_zero = 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 BCD_fractional_part { buff[i] = '0' + d i++ } dst = append(dst, buff[:i]...) // write fractional part into destination return dst }