484 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			484 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package ccxt
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"math"
 | 
						|
	"math/big"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
)
 | 
						|
 | 
						|
type PreciseStruct struct {
 | 
						|
	Decimals   interface{}
 | 
						|
	integer    *big.Int
 | 
						|
	baseNumber int64
 | 
						|
}
 | 
						|
 | 
						|
var Precise = &PreciseStruct{}
 | 
						|
 | 
						|
func NewPrecise(number2 interface{}, dec2 ...interface{}) *PreciseStruct {
 | 
						|
	var dec int
 | 
						|
	if len(dec2) > 0 {
 | 
						|
		dec = int(ParseInt(dec2[0]))
 | 
						|
	} else {
 | 
						|
		dec = math.MinInt32
 | 
						|
	}
 | 
						|
 | 
						|
	number := fmt.Sprintf("%v", number2)
 | 
						|
	p := &PreciseStruct{
 | 
						|
		baseNumber: 10,
 | 
						|
	}
 | 
						|
 | 
						|
	if dec == math.MinInt32 {
 | 
						|
		modified := 0
 | 
						|
		numberLowerCase := strings.ToLower(number)
 | 
						|
		if strings.Contains(numberLowerCase, "e") {
 | 
						|
			parts := strings.Split(numberLowerCase, "e")
 | 
						|
			number = parts[0]
 | 
						|
			modified, _ = strconv.Atoi(parts[1])
 | 
						|
		}
 | 
						|
		decimalIndex := strings.Index(number, ".")
 | 
						|
		var newDecimals int
 | 
						|
		if decimalIndex > -1 {
 | 
						|
			newDecimals = len(number) - decimalIndex - 1
 | 
						|
		} else {
 | 
						|
			newDecimals = 0
 | 
						|
		}
 | 
						|
		p.Decimals = newDecimals
 | 
						|
		integerString := strings.Replace(number, ".", "", -1)
 | 
						|
		p.integer = new(big.Int)
 | 
						|
		p.integer.SetString(integerString, 10)
 | 
						|
		p.Decimals = newDecimals - modified
 | 
						|
	} else {
 | 
						|
		p.integer = new(big.Int)
 | 
						|
		p.integer.SetString(number, 10)
 | 
						|
		p.Decimals = dec
 | 
						|
	}
 | 
						|
 | 
						|
	return p
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) Mul(other *PreciseStruct) *PreciseStruct {
 | 
						|
	integer := new(big.Int).Mul(p.integer, other.integer)
 | 
						|
	decimals := p.Decimals.(int) + other.Decimals.(int)
 | 
						|
	return NewPrecise(integer.String(), decimals)
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) Div(other *PreciseStruct, precision2 ...interface{}) *PreciseStruct {
 | 
						|
	precision := int64(18)
 | 
						|
	if len(precision2) > 0 {
 | 
						|
		precision = ParseInt(precision2[0])
 | 
						|
	}
 | 
						|
	distance := precision - ParseInt(p.Decimals) + ParseInt(other.Decimals)
 | 
						|
	var numerator *big.Int
 | 
						|
 | 
						|
	if distance == 0 {
 | 
						|
		numerator = p.integer
 | 
						|
	} else if distance < 0 {
 | 
						|
		exponent := new(big.Int).Exp(big.NewInt(p.baseNumber), big.NewInt(int64(-distance)), nil)
 | 
						|
		numerator = new(big.Int).Div(p.integer, exponent)
 | 
						|
	} else {
 | 
						|
		exponent := new(big.Int).Exp(big.NewInt(p.baseNumber), big.NewInt(int64(distance)), nil)
 | 
						|
		numerator = new(big.Int).Mul(p.integer, exponent)
 | 
						|
	}
 | 
						|
	result := new(big.Int).Div(numerator, other.integer)
 | 
						|
	return NewPrecise(result.String(), precision)
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) Add(other *PreciseStruct) *PreciseStruct {
 | 
						|
	if p.Decimals == other.Decimals {
 | 
						|
		integerResult := new(big.Int).Add(p.integer, other.integer)
 | 
						|
		return NewPrecise(integerResult.String(), p.Decimals.(int))
 | 
						|
	} else {
 | 
						|
		var smaller, bigger *PreciseStruct
 | 
						|
		if p.Decimals.(int) < other.Decimals.(int) {
 | 
						|
			smaller = p
 | 
						|
			bigger = other
 | 
						|
		} else {
 | 
						|
			smaller = other
 | 
						|
			bigger = p
 | 
						|
		}
 | 
						|
		exponent := bigger.Decimals.(int) - smaller.Decimals.(int)
 | 
						|
		normalized := new(big.Int).Mul(smaller.integer, new(big.Int).Exp(big.NewInt(p.baseNumber), big.NewInt(int64(exponent)), nil))
 | 
						|
		result := new(big.Int).Add(normalized, bigger.integer)
 | 
						|
		return NewPrecise(result.String(), bigger.Decimals.(int))
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) Mod(other *PreciseStruct) *PreciseStruct {
 | 
						|
	rationizerNumerator := int(math.Max(float64(-p.Decimals.(int)+other.Decimals.(int)), 0))
 | 
						|
	numerator := new(big.Int).Mul(p.integer, new(big.Int).Exp(big.NewInt(p.baseNumber), big.NewInt(int64(rationizerNumerator)), nil))
 | 
						|
	rationizerDenominator := int(math.Max(float64(-other.Decimals.(int)+p.Decimals.(int)), 0))
 | 
						|
	denominator := new(big.Int).Mul(other.integer, new(big.Int).Exp(big.NewInt(p.baseNumber), big.NewInt(int64(rationizerDenominator)), nil))
 | 
						|
	result := new(big.Int).Mod(numerator, denominator)
 | 
						|
	return NewPrecise(result.String(), rationizerDenominator+other.Decimals.(int))
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) Sub(other *PreciseStruct) *PreciseStruct {
 | 
						|
	negative := NewPrecise(new(big.Int).Neg(other.integer).String(), other.Decimals.(int))
 | 
						|
	return p.Add(negative)
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) Or(other *PreciseStruct) *PreciseStruct {
 | 
						|
	integer := new(big.Int).Or(p.integer, other.integer)
 | 
						|
	decimals := p.Decimals.(int) + other.Decimals.(int)
 | 
						|
	return NewPrecise(integer.String(), decimals)
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) Neg() *PreciseStruct {
 | 
						|
	return NewPrecise(new(big.Int).Neg(p.integer).String(), p.Decimals.(int))
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) Min(other *PreciseStruct) *PreciseStruct {
 | 
						|
	if p.Lt(other) {
 | 
						|
		return p
 | 
						|
	}
 | 
						|
	return other
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) Max(other *PreciseStruct) *PreciseStruct {
 | 
						|
	if p.Gt(other) {
 | 
						|
		return p
 | 
						|
	}
 | 
						|
	return other
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) Gt(other *PreciseStruct) bool {
 | 
						|
	sum := p.Sub(other)
 | 
						|
	return sum.integer.Cmp(big.NewInt(0)) > 0
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) Ge(other *PreciseStruct) bool {
 | 
						|
	sum := p.Sub(other)
 | 
						|
	return sum.integer.Cmp(big.NewInt(0)) >= 0
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) Lt(other *PreciseStruct) bool {
 | 
						|
	return other.Gt(p)
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) Le(other *PreciseStruct) bool {
 | 
						|
	return other.Ge(p)
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) Abs() *PreciseStruct {
 | 
						|
	var result *big.Int
 | 
						|
	if p.integer.Cmp(big.NewInt(0)) < 0 {
 | 
						|
		result = new(big.Int).Mul(p.integer, big.NewInt(-1))
 | 
						|
	} else {
 | 
						|
		result = p.integer
 | 
						|
	}
 | 
						|
	return NewPrecise(result.String(), p.Decimals.(int))
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) Reduce() *PreciseStruct {
 | 
						|
	str := p.integer.String()
 | 
						|
	start := len(str) - 1
 | 
						|
	if start == 0 {
 | 
						|
		if str == "0" {
 | 
						|
			p.Decimals = 0
 | 
						|
		}
 | 
						|
		return p
 | 
						|
	}
 | 
						|
	i := start
 | 
						|
	for ; i >= 0; i-- {
 | 
						|
		if str[i] != '0' {
 | 
						|
			break
 | 
						|
		}
 | 
						|
	}
 | 
						|
	difference := start - i
 | 
						|
	if difference == 0 {
 | 
						|
		return p
 | 
						|
	}
 | 
						|
	p.Decimals = int(ParseInt(p.Decimals)) - difference
 | 
						|
	p.integer = new(big.Int)
 | 
						|
	p.integer.SetString(str[:i+1], 10)
 | 
						|
	return p
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) Equals(other *PreciseStruct) bool {
 | 
						|
	p.Reduce()
 | 
						|
	other.Reduce()
 | 
						|
	return p.integer.Cmp(other.integer) == 0 && p.Decimals.(int) == other.Decimals.(int)
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) String() string {
 | 
						|
	p.Reduce()
 | 
						|
	sign := ""
 | 
						|
	var abs *big.Int
 | 
						|
	if p.integer.Cmp(big.NewInt(0)) < 0 {
 | 
						|
		sign = "-"
 | 
						|
		abs = new(big.Int).Mul(p.integer, big.NewInt(-1))
 | 
						|
	} else {
 | 
						|
		abs = p.integer
 | 
						|
	}
 | 
						|
	absParsed := abs.String()
 | 
						|
	padSize := p.Decimals.(int)
 | 
						|
	if padSize < 0 {
 | 
						|
		padSize = 0
 | 
						|
	}
 | 
						|
	integerArray := strings.Split(fmt.Sprintf("%0*s", padSize, absParsed), "")
 | 
						|
	index := len(integerArray) - p.Decimals.(int)
 | 
						|
	item := ""
 | 
						|
	if index == 0 {
 | 
						|
		item = "0."
 | 
						|
	} else if p.Decimals.(int) < 0 {
 | 
						|
		item = strings.Repeat("0", -p.Decimals.(int))
 | 
						|
	} else if p.Decimals.(int) == 0 {
 | 
						|
		item = ""
 | 
						|
	} else {
 | 
						|
		item = "."
 | 
						|
	}
 | 
						|
	arrayIndex := index
 | 
						|
	if arrayIndex > len(integerArray) {
 | 
						|
		arrayIndex = len(integerArray)
 | 
						|
	}
 | 
						|
	integerArray = append(integerArray[:arrayIndex], append([]string{item}, integerArray[arrayIndex:]...)...)
 | 
						|
	return sign + strings.Join(integerArray, "")
 | 
						|
}
 | 
						|
 | 
						|
func StringMul(string1, string2 interface{}) string {
 | 
						|
	if string1 == nil || string2 == nil {
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
	return NewPrecise(string1.(string)).Mul(NewPrecise(string2.(string))).String()
 | 
						|
}
 | 
						|
 | 
						|
func StringDiv(string1, string2 interface{}, precision ...interface{}) string {
 | 
						|
	if string1 == nil || string2 == nil {
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
	string2Precise := NewPrecise(string2.(string))
 | 
						|
	if string2Precise.integer.Cmp(big.NewInt(0)) == 0 {
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
	stringDiv := NewPrecise(string1.(string)).Div(string2Precise, precision...)
 | 
						|
	return stringDiv.String()
 | 
						|
}
 | 
						|
 | 
						|
func StringSub(string1, string2 interface{}) string {
 | 
						|
	if string1 == nil || string2 == nil {
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
	return NewPrecise(string1.(string)).Sub(NewPrecise(string2.(string))).String()
 | 
						|
}
 | 
						|
 | 
						|
// func (this *PreciseStruct) stringSub(string1, string2 interface{}) string {
 | 
						|
// 	return StringSub(string1, string2)
 | 
						|
// }
 | 
						|
 | 
						|
func StringAdd(string1, string2 interface{}) string {
 | 
						|
	if string1 == nil && string2 == nil {
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
	if string1 == nil {
 | 
						|
		return string2.(string)
 | 
						|
	}
 | 
						|
	if string2 == nil {
 | 
						|
		return string1.(string)
 | 
						|
	}
 | 
						|
	return NewPrecise(string1.(string)).Add(NewPrecise(string2.(string))).String()
 | 
						|
}
 | 
						|
 | 
						|
func StringOr(string1, string2 interface{}) string {
 | 
						|
	if string1 == nil || string2 == nil {
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
	return NewPrecise(string1.(string)).Or(NewPrecise(string2.(string))).String()
 | 
						|
}
 | 
						|
 | 
						|
func StringGt(a, b interface{}) bool {
 | 
						|
	if a == nil || b == nil {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	return NewPrecise(a.(string)).Gt(NewPrecise(b.(string)))
 | 
						|
}
 | 
						|
 | 
						|
func StringEq(a, b interface{}) bool {
 | 
						|
	if a == nil || b == nil {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	return NewPrecise(a.(string)).Equals(NewPrecise(b.(string)))
 | 
						|
}
 | 
						|
 | 
						|
func StringMax(a, b interface{}) string {
 | 
						|
	if a == nil || b == nil {
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
	return NewPrecise(a.(string)).Max(NewPrecise(b.(string))).String()
 | 
						|
}
 | 
						|
 | 
						|
func StringEquals(a, b interface{}) bool {
 | 
						|
	if a == nil || b == nil {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	return NewPrecise(a.(string)).Equals(NewPrecise(b.(string)))
 | 
						|
}
 | 
						|
 | 
						|
func StringMin(string1, string2 interface{}) string {
 | 
						|
	if string1 == nil || string2 == nil {
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
	return NewPrecise(string1.(string)).Min(NewPrecise(string2.(string))).String()
 | 
						|
}
 | 
						|
 | 
						|
func StringLt(a, b interface{}) bool {
 | 
						|
	if a == nil || b == nil {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	return NewPrecise(a.(string)).Lt(NewPrecise(b.(string)))
 | 
						|
}
 | 
						|
 | 
						|
func StringAbs(a interface{}) string {
 | 
						|
	if a == nil {
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
	return NewPrecise(a.(string)).Abs().String()
 | 
						|
}
 | 
						|
 | 
						|
func StringNeg(a interface{}) string {
 | 
						|
	if a == nil {
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
	return NewPrecise(a.(string)).Neg().String()
 | 
						|
}
 | 
						|
 | 
						|
func StringLe(a, b interface{}) bool {
 | 
						|
	if a == nil || b == nil {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	return NewPrecise(a.(string)).Le(NewPrecise(b.(string)))
 | 
						|
}
 | 
						|
 | 
						|
func StringGe(a, b interface{}) bool {
 | 
						|
	if a == nil || b == nil {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	return NewPrecise(a.(string)).Ge(NewPrecise(b.(string)))
 | 
						|
}
 | 
						|
 | 
						|
func StringMod(a, b interface{}) string {
 | 
						|
	if a == nil || b == nil {
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
	return NewPrecise(a.(string)).Mod(NewPrecise(b.(string))).String()
 | 
						|
}
 | 
						|
 | 
						|
func (p *PreciseStruct) ToString() string {
 | 
						|
	p.Reduce() // Call the reduce method if any
 | 
						|
 | 
						|
	// Determine the sign and absolute value
 | 
						|
	var sign string
 | 
						|
	abs := new(big.Int)
 | 
						|
	if p.integer.Sign() < 0 {
 | 
						|
		sign = "-"
 | 
						|
		abs.Neg(p.integer) // Negate the integer to get the absolute value
 | 
						|
	} else {
 | 
						|
		sign = ""
 | 
						|
		abs.Set(p.integer) // Copy the positive value of the integer
 | 
						|
	}
 | 
						|
 | 
						|
	intPDecimals := ParseInt(p.Decimals)
 | 
						|
 | 
						|
	// Convert the absolute value to a string
 | 
						|
	// integerStr := fmt.Sprintf("%0*d", intPDecimals+ParseInt(len(abs.String())), abs)
 | 
						|
	// integerArray := strings.Split(integerStr, "")
 | 
						|
	// // Calculate the index to insert the decimal point
 | 
						|
	var item string
 | 
						|
 | 
						|
	absParsed := abs.String()
 | 
						|
	padSize := 0
 | 
						|
	if intPDecimals > 0 {
 | 
						|
		padSize = int(intPDecimals)
 | 
						|
	}
 | 
						|
	absParsed = fmt.Sprintf("%0*s", len(absParsed)+padSize, absParsed)
 | 
						|
	integerArray := strings.Split(absParsed, "")
 | 
						|
	// index := len(integerArray) - intPDecimals
 | 
						|
	index := ParseInt(len(integerArray)) - intPDecimals
 | 
						|
 | 
						|
	// Handle cases based on the value of decimals
 | 
						|
	if index == 0 {
 | 
						|
		item = "0."
 | 
						|
	} else if intPDecimals < 0 {
 | 
						|
		item = strings.Repeat("0", -int(intPDecimals))
 | 
						|
	} else if intPDecimals == 0 {
 | 
						|
		item = ""
 | 
						|
	} else {
 | 
						|
		item = "."
 | 
						|
	}
 | 
						|
 | 
						|
	arrayIndex := index
 | 
						|
	arrayLength := ParseInt(len(integerArray))
 | 
						|
	if index > arrayLength {
 | 
						|
		arrayIndex = arrayLength
 | 
						|
	}
 | 
						|
	integerArray = append(integerArray[:arrayIndex], append([]string{item}, integerArray[arrayIndex:]...)...)
 | 
						|
	return sign + strings.Join(integerArray, "")
 | 
						|
}
 | 
						|
 | 
						|
// wrappers
 | 
						|
 | 
						|
func (e *PreciseStruct) StringMul(string1, string2 interface{}) string {
 | 
						|
	return StringMul(string1, string2)
 | 
						|
}
 | 
						|
 | 
						|
func (e *PreciseStruct) StringDiv(string1, string2 interface{}, precision ...interface{}) string {
 | 
						|
	return StringDiv(string1, string2, precision...)
 | 
						|
}
 | 
						|
 | 
						|
func (e *PreciseStruct) StringSub(string1, string2 interface{}) string {
 | 
						|
	return StringSub(string1, string2)
 | 
						|
}
 | 
						|
 | 
						|
func (e *PreciseStruct) StringAdd(string1, string2 interface{}) string {
 | 
						|
	return StringAdd(string1, string2)
 | 
						|
}
 | 
						|
 | 
						|
func (e *PreciseStruct) StringOr(string1, string2 interface{}) string {
 | 
						|
	return StringOr(string1, string2)
 | 
						|
}
 | 
						|
 | 
						|
func (e *PreciseStruct) StringGt(a, b interface{}) bool {
 | 
						|
	return StringGt(a, b)
 | 
						|
}
 | 
						|
 | 
						|
func (e *PreciseStruct) StringEq(a, b interface{}) bool {
 | 
						|
	return StringEq(a, b)
 | 
						|
}
 | 
						|
 | 
						|
func (e *PreciseStruct) StringMax(a, b interface{}) string {
 | 
						|
	return StringMax(a, b)
 | 
						|
}
 | 
						|
 | 
						|
func (e *PreciseStruct) StringEquals(a, b interface{}) bool {
 | 
						|
	return StringEquals(a, b)
 | 
						|
}
 | 
						|
 | 
						|
func (e *PreciseStruct) StringMin(string1, string2 interface{}) string {
 | 
						|
	return StringMin(string1, string2)
 | 
						|
}
 | 
						|
 | 
						|
func (e *PreciseStruct) StringLt(a, b interface{}) bool {
 | 
						|
	return StringLt(a, b)
 | 
						|
}
 | 
						|
 | 
						|
func (e *PreciseStruct) StringAbs(a interface{}) string {
 | 
						|
	return StringAbs(a)
 | 
						|
}
 | 
						|
 | 
						|
func (e *PreciseStruct) StringNeg(a interface{}) string {
 | 
						|
	return StringNeg(a)
 | 
						|
}
 | 
						|
 | 
						|
func (e *PreciseStruct) StringLe(a, b interface{}) bool {
 | 
						|
	return StringLe(a, b)
 | 
						|
}
 | 
						|
 | 
						|
func (e *PreciseStruct) StringGe(a, b interface{}) bool {
 | 
						|
	return StringGe(a, b)
 | 
						|
}
 | 
						|
 | 
						|
func (e *PreciseStruct) StringMod(a, b interface{}) string {
 | 
						|
	return StringMod(a, b)
 | 
						|
}
 |