github.com/vipernet-xyz/tm@v0.34.24/libs/math/fraction.go (about)

     1  package math
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"math"
     7  	"strconv"
     8  	"strings"
     9  )
    10  
    11  // Fraction defined in terms of a numerator divided by a denominator in uint64
    12  // format. Fraction must be positive.
    13  type Fraction struct {
    14  	// The portion of the denominator in the faction, e.g. 2 in 2/3.
    15  	Numerator uint64 `json:"numerator"`
    16  	// The value by which the numerator is divided, e.g. 3 in 2/3.
    17  	Denominator uint64 `json:"denominator"`
    18  }
    19  
    20  func (fr Fraction) String() string {
    21  	return fmt.Sprintf("%d/%d", fr.Numerator, fr.Denominator)
    22  }
    23  
    24  // ParseFractions takes the string of a fraction as input i.e "2/3" and converts this
    25  // to the equivalent fraction else returns an error. The format of the string must be
    26  // one number followed by a slash (/) and then the other number.
    27  func ParseFraction(f string) (Fraction, error) {
    28  	o := strings.Split(f, "/")
    29  	if len(o) != 2 {
    30  		return Fraction{}, errors.New("incorrect formating: should have a single slash i.e. \"1/3\"")
    31  	}
    32  	numerator, err := strconv.ParseUint(o[0], 10, 64)
    33  	if err != nil {
    34  		return Fraction{}, fmt.Errorf("incorrect formatting, err: %w", err)
    35  	}
    36  
    37  	denominator, err := strconv.ParseUint(o[1], 10, 64)
    38  	if err != nil {
    39  		return Fraction{}, fmt.Errorf("incorrect formatting, err: %w", err)
    40  	}
    41  	if denominator == 0 {
    42  		return Fraction{}, errors.New("denominator can't be 0")
    43  	}
    44  	if numerator > math.MaxInt64 || denominator > math.MaxInt64 {
    45  		return Fraction{}, fmt.Errorf("value overflow, numerator and denominator must be less than %d", int64(math.MaxInt64))
    46  	}
    47  	return Fraction{Numerator: numerator, Denominator: denominator}, nil
    48  }