Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support similar to math.Ceil(X) function #236

Closed
wpecker opened this issue Jul 9, 2021 · 5 comments
Closed

Add support similar to math.Ceil(X) function #236

wpecker opened this issue Jul 9, 2021 · 5 comments

Comments

@wpecker
Copy link

wpecker commented Jul 9, 2021

func CeilingD(value decimal.Decimal) decimal.Decimal {
	x, _ := value.Float64()

	if x < 500.0 {
		return decimal.NewFromFloat(math.Ceil(x/10.0) * 10.0)
	}

	if x < 1000.0 {
		return decimal.NewFromFloat(math.Ceil(x/50.0) * 50.0)
	}

	if x < 5000.0 {
		return decimal.NewFromFloat(math.Ceil(x/100.0) * 100.0)
	}

	if x < 10000.0 {
		return decimal.NewFromFloat(math.Ceil(x/500.0) * 500.0)
	}

	if x < 50000.0 {
		return decimal.NewFromFloat(math.Ceil(x/1000.0) * 1000.0)
	}

	if x < 500000.0 {
		return decimal.NewFromFloat(math.Ceil(x/5000.0) * 5000.0)
	}
	return decimal.NewFromFloat(math.Ceil(x/10000.0) * 10000.0)
}
@mwoss
Copy link
Member

mwoss commented Jul 10, 2021

Hi @Vinerr! RoundCeil has been implemented in the #220. Such functionality is available on the main branch, and will be released officially in 1.3.0

@wpecker
Copy link
Author

wpecker commented Jul 11, 2021

@mwoss Ok, Thanks, I have perfectly solved my problem based on v1.2.0

var (
	CeilFloorBase10       = decimal.NewFromFloat(10.0)
	CeilFloorBase50       = decimal.NewFromFloat(50.0)
	CeilFloorBase1B       = decimal.NewFromFloat(100.0)
	CeilFloorBase5B       = decimal.NewFromFloat(500.0)
	CeilFloorBase1Q       = decimal.NewFromFloat(1000.0)
	CeilFloorBase5Q       = decimal.NewFromFloat(5000.0)
	CeilFloorBase1W       = decimal.NewFromFloat(10000.0)
	CeilFloorBase2W       = decimal.NewFromFloat(20000.0)
	CeilFloorBase5W       = decimal.NewFromFloat(50000.0)
	CeilFloorBase10W      = decimal.NewFromFloat(100000.0)
	CeilFloorBase20W      = decimal.NewFromFloat(200000.0)
	CeilFloorBase50W      = decimal.NewFromFloat(500000.0)
	CeilFloorBase100W     = decimal.NewFromFloat(1000000.0)
	CeilFloorBase500W     = decimal.NewFromFloat(5000000.0)
	CeilFloorBase1000W    = decimal.NewFromFloat(10000000.0)
	CeilFloorBase5000W    = decimal.NewFromFloat(50000000.0)
	CeilFloorBase1Billion = decimal.NewFromFloat(100000000.0)
)

var (
	CeilFloorThreshold5B           = CeilFloorBase5B                        // CeilFloorBase10
	CeilFloorThreshold1Q           = CeilFloorBase1Q                        // CeilFloorBase50
	CeilFloorThreshold5Q           = CeilFloorBase5Q                        // CeilFloorBase1B
	CeilFloorThreshold1W           = CeilFloorBase1W                        // CeilFloorBase5B
	CeilFloorThreshold5W           = CeilFloorBase5W                        // CeilFloorBase1Q
	CeilFloorThreshold10W          = CeilFloorBase10W                       // CeilFloorBase5Q
	CeilFloorThreshold100W         = CeilFloorBase100W                      // CeilFloorBase1W
	CeilFloorThreshold500W         = CeilFloorBase500W                      // CeilFloorBase2W
	CeilFloorThreshold1000W        = CeilFloorBase1000W                     // CeilFloorBase5W
	CeilFloorThreshold5000W        = CeilFloorBase5000W                     // CeilFloorBase10W
	CeilFloorThreshold1Billion     = CeilFloorBase1Billion                  // CeilFloorBase20W
	CeilFloorThreshold5Billion     = CeilFloorBase1Billion.Mul(Five)        // CeilFloorBase50W
	CeilFloorThreshold10Billion    = CeilFloorBase1Billion.Mul(Ten)         // CeilFloorBase100W
	CeilFloorThreshold100Billion   = CeilFloorBase1Billion.Mul(OneHundred)  // CeilFloorBase500W
	CeilFloorThreshold500Billion   = CeilFloorThreshold100Billion.Mul(Five) // CeilFloorBase1000W
	CeilFloorThreshold1000Billion  = CeilFloorThreshold500Billion.Mul(Two)  // CeilFloorBase5000W
	CeilFloorThreshold10000Billion = CeilFloorThreshold1000Billion.Mul(Ten) // CeilFloorBase1Billion
)
var (
	CeilFloorThresholdMap = map[uint8]decimal.Decimal{
		1:  CeilFloorThreshold5B,
		2:  CeilFloorThreshold1Q,
		3:  CeilFloorThreshold5Q,
		4:  CeilFloorThreshold1W,
		5:  CeilFloorThreshold5W,
		6:  CeilFloorThreshold10W,
		7:  CeilFloorThreshold100W,
		8:  CeilFloorThreshold500W,
		9:  CeilFloorThreshold1000W,
		10: CeilFloorThreshold5000W,
		11: CeilFloorThreshold1Billion,
		12: CeilFloorThreshold5Billion,
		13: CeilFloorThreshold10Billion,
		14: CeilFloorThreshold100Billion,
		15: CeilFloorThreshold500Billion,
		16: CeilFloorThreshold1000Billion,
		17: CeilFloorThreshold10000Billion,
	}

	CeilFloorBaseMap = map[uint8]decimal.Decimal{
		1:  CeilFloorBase10,
		2:  CeilFloorBase50,
		3:  CeilFloorBase1B,
		4:  CeilFloorBase5B,
		5:  CeilFloorBase1Q,
		6:  CeilFloorBase5Q,
		7:  CeilFloorBase1W,
		8:  CeilFloorBase2W,
		9:  CeilFloorBase5W,
		10: CeilFloorBase10W,
		11: CeilFloorBase20W,
		12: CeilFloorBase50W,
		13: CeilFloorBase100W,
		14: CeilFloorBase500W,
		15: CeilFloorBase1000W,
		16: CeilFloorBase5000W,
		17: CeilFloorBase1Billion,
	}
)

func CeilingD(x decimal.Decimal) decimal.Decimal {
	for i := uint8(1); i < 18; i++ {
		if x.LessThanOrEqual(com.CeilFloorThresholdMap[i]) {
			base := com.CeilFloorBaseMap[i]
			return x.Div(base).Ceil().Mul(base)
		}
	}
	return x
}

func FlooringD(x decimal.Decimal) decimal.Decimal {
	for i := uint8(1); i < 18; i++ {
		if x.LessThanOrEqual(com.CeilFloorThresholdMap[i]) {
			base := com.CeilFloorBaseMap[i]
			return x.Div(base).Floor().Mul(base)
		}
	}
	return x
}

@wpecker wpecker closed this as completed Jul 11, 2021
@wpecker
Copy link
Author

wpecker commented Jul 11, 2021

like this:

// 1000     10
// 10000    100
// 100000   1000
// 1000000  10000
// 10000000 100000
func CeilD(x decimal.Decimal) decimal.Decimal {
	if x.LessThan(com.OneHundred) {
		return x.Div(com.Ten).Ceil().Mul(com.Ten)
	}
	y := x.Div(com.OneHundred).Round(0)
	base := com.One
	for {
		if y.IsZero() {
			break
		}
		y = y.Div(com.Ten).Round(0)
		base = base.Mul(com.Ten)
	}
	return x.Div(base).Ceil().Mul(base)
}

func FloorD(x decimal.Decimal) decimal.Decimal {
	if x.LessThan(com.OneHundred) {
		return x.Div(com.Ten).Ceil().Mul(com.Ten)
	}
	y := x.Div(com.OneHundred).Round(0)
	base := com.One
	for {
		if y.IsZero() {
			break
		}
		y = y.Div(com.Ten).Round(0)
		base = base.Mul(com.Ten)
	}
	return x.Div(base).Floor().Mul(base)
}

// 1000     10
// 10000    100
// 100000   1000
// 1000000  10000
// 10000000 100000
func Ceil(x float64) float64 {
	if x < 100.0 {
		return math.Ceil(x/10.0) * 10.0
	}
	y := math.Trunc(x / 100.0)
	base := 1.0
	for {
		if y == 0 {
			break
		}
		y = math.Trunc(y / 10.0)
		base = base * 10.0
	}
	return math.Ceil(x/base) * base
}

func Floor(x float64) float64 {
	if x < 100.0 {
		return math.Floor(x/10.0) * 10.0
	}
	y := math.Trunc(x / 100.0)
	base := 1.0
	for {
		if y == 0 {
			break
		}
		y = math.Trunc(y / 10.0)
		base = base * 10.0
	}
	return math.Floor(x/base) * base
}

@mwoss
Copy link
Member

mwoss commented Jul 11, 2021

Does RoundCeil that exists on the main branch not meet your expectation or it does not work correctly?
Why you had to implement your version of it? Just curious.

@wpecker
Copy link
Author

wpecker commented Jul 12, 2021

@mwoss Yes, RoundCeil is not what I expected

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants