// EncodeDecimal encodes a decimal d into a byte slice which can be sorted lexicographically later. // EncodeDecimal guarantees that the encoded value is in ascending order for comparison. // Decimal encoding: // EncodeInt -> value sign // EncodeInt -> exp sign // EncodeInt -> exp value // EncodeBytes -> abs value bytes func EncodeDecimal(b []byte, d mysql.Decimal) []byte { if d.Equals(mysql.ZeroDecimal) { return EncodeInt(b, zeroSign) } v := d.BigIntValue() valSign := codecSign(int64(v.Sign())) absVal := new(big.Int) absVal.Abs(v) value := []byte(absVal.String()) // Trim right side "0", like "12.34000" -> "12.34" or "0.1234000" -> "0.1234". if d.Exponent() != 0 { value = bytes.TrimRight(value, "0") } // Get exp and value, format is "value":"exp". // like "12.34" -> "0.1234":"2". // like "-0.01234" -> "-0.1234":"-1". exp := int64(0) div := big.NewInt(10) for ; ; exp++ { if absVal.Sign() == 0 { break } absVal = absVal.Div(absVal, div) } expVal := exp + int64(d.Exponent()) expSign := codecSign(expVal) // For negtive exp, do bit reverse for exp. // For negtive decimal, do bit reverse for exp and value. expVal = encodeExp(expVal, expSign, valSign) codecValue(value, valSign) r := EncodeInt(b, valSign) r = EncodeInt(r, expSign) r = EncodeInt(r, expVal) r = EncodeBytes(r, value) return r }
// EncodeDecimal encodes a decimal d into a byte slice which can be sorted lexicographically later. // EncodeDecimal guarantees that the encoded value is in ascending order for comparison. // Decimal encoding: // Byte -> value sign // EncodeInt -> exp value // EncodeBytes -> abs value bytes func EncodeDecimal(b []byte, d mysql.Decimal) []byte { if d.Equals(mysql.ZeroDecimal) { return append(b, byte(zeroSign)) } v := d.BigIntValue() valSign := codecSign(int64(v.Sign())) absVal := new(big.Int) absVal.Abs(v) // Get exp and value, format is "value":"exp". // like "12.34" -> "0.1234":"2". // like "-0.01234" -> "-0.1234":"-1". exp := int64(0) div := big.NewInt(10) mod := big.NewInt(0) value := []byte{} for ; ; exp++ { if absVal.Sign() == 0 { break } mod.Mod(absVal, div) absVal.Div(absVal, div) value = append([]byte(strconv.Itoa(int(mod.Int64()))), value...) } value = bytes.TrimRight(value, "0") expVal := exp + int64(d.Exponent()) if valSign == negativeSign { expVal = -expVal } b = append(b, byte(valSign)) b = EncodeInt(b, expVal) if valSign == negativeSign { b = EncodeBytesDesc(b, value) } else { b = EncodeBytes(b, value) } return b }