Description
tl;dr How to split value x ways correctly?
Disclaimer: personally I always try to first look for information and details about specific subjects before asking. I hope that this issue may help other people like me who try to move from shopspring/decimal to a library with better performance.
Problem, I’m currently facing is splitting number X ways. For example if we have value 100 that has to be split between 3 entities:
I will have to give two of them 33.33333 and one of them will receive the remainder which is 33.33334. After adding all the values together I will get the base value which is 100.
I understand that representing fractions of value would sometimes require an infinite amount of memory but it’s possible to do this with specified precision which for library shopspring/decimal is 16.
Here is the example code of splitting value x ways:
package main
import (
"fmt"
"github.com/shopspring/decimal"
)
func split(value, number int) (decimal.Decimal, decimal.Decimal){
baseValue := decimal.NewFromInt(int64(value))
num := decimal.NewFromInt(int64(number))
lower := baseValue.Div(num)
higher := lower.Mul(num)
higher = baseValue.Sub(higher).Add(lower)
return higher, lower
}
func check(higher, lower decimal.Decimal, number int) decimal.Decimal{
baseValue := decimal.Zero
for i := 1 ; i < number ; i++ {
baseValue = baseValue.Add(lower)
}
baseValue = baseValue.Add(higher)
return baseValue
}
func main(){
baseValue := 100
number := 13
higher, lower := split(baseValue,number)
baseValue2 := check(higher,lower,number)
if baseValue2.Equal(decimal.NewFromInt(int64(baseValue))){
fmt.Println("Correct")
} else {
fmt.Println("Incorrect")
}
}
So far above code always return correct values for most of my test cases.
Creating similar code with this library will return correct results for values like 100 split 3 ways. But for example 100 split 13 ways will return a value of 99.9999… .
Is it possible to achieve the same results using this decimal library?