github.com/searKing/golang/go@v1.2.117/format/multiple_prefix/binary_multiple_prefix.go (about)

     1  // Copyright 2020 The searKing Author. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package multiple_prefix
     6  
     7  import (
     8  	"math"
     9  	"math/big"
    10  
    11  	math_ "github.com/searKing/golang/go/math"
    12  )
    13  
    14  // 计量单位,如Ki、Mi、Gi、Ti
    15  type BinaryMultiplePrefix struct {
    16  	multiplePrefix
    17  }
    18  
    19  // https://physics.nist.gov/cuu/Units/binary.html
    20  //
    21  //				Prefixes for binary multiples
    22  //	Factor 	Name 	Symbol 	Origin					Derivation
    23  //	210		kibi	Ki		kilobinary: (2^10)^1	kilo: (10^3)^1
    24  //	220		mebi	Mi		megabinary: (2^10)^2 	mega: (10^3)^2
    25  //	230		gibi	Gi		gigabinary: (2^10)^3	giga: (10^3)^3
    26  //	240		tebi	Ti		terabinary: (2^10)^4	tera: (10^3)^4
    27  //	250		pebi	Pi		petabinary: (2^10)^5	peta: (10^3)^5
    28  //	260		exbi	Ei		exabinary:  (2^10)^6	exa:  (10^3)^6
    29  var (
    30  	BinaryMultiplePrefixMin  = BinaryMultiplePrefixOne
    31  	BinaryMultiplePrefixOne  = BinaryMultiplePrefix{multiplePrefix{2, 0, "", ""}}        // BaseNumber^0	10^0
    32  	BinaryMultiplePrefixKibi = BinaryMultiplePrefix{multiplePrefix{2, 10, "kibi", "Ki"}} // BaseNumber^1	10^+03
    33  	BinaryMultiplePrefixMebi = BinaryMultiplePrefix{multiplePrefix{2, 20, "mebi", "Mi"}} // BaseNumber^2	10^+06
    34  	BinaryMultiplePrefixGibi = BinaryMultiplePrefix{multiplePrefix{2, 30, "gibi", "Gi"}} // BaseNumber^3	10^+09
    35  	BinaryMultiplePrefixTebi = BinaryMultiplePrefix{multiplePrefix{2, 40, "tebi", "Ti"}} // BaseNumber^4	10^+12
    36  	BinaryMultiplePrefixPebi = BinaryMultiplePrefix{multiplePrefix{2, 50, "pebi", "Pi"}} // BaseNumber^5	10^+15
    37  	BinaryMultiplePrefixExbi = BinaryMultiplePrefix{multiplePrefix{2, 60, "exbi", "Ei"}} // BaseNumber^6	10^+18
    38  	BinaryMultiplePrefixMax  = BinaryMultiplePrefixExbi
    39  )
    40  
    41  var (
    42  	BinaryMultiplePrefixTODO = BinaryMultiplePrefix{multiplePrefix{base: 2}}
    43  )
    44  var binaryNegativeMultiplePrefixes = [...]BinaryMultiplePrefix{}
    45  var binaryZeroMultiplePrefixes = [...]BinaryMultiplePrefix{BinaryMultiplePrefixOne}
    46  var binaryPositiveMultiplePrefixes = [...]BinaryMultiplePrefix{BinaryMultiplePrefixKibi, BinaryMultiplePrefixMebi, BinaryMultiplePrefixGibi, BinaryMultiplePrefixTebi, BinaryMultiplePrefixPebi, BinaryMultiplePrefixExbi}
    47  
    48  func (dp BinaryMultiplePrefix) Copy() *BinaryMultiplePrefix {
    49  	var dp2 = &BinaryMultiplePrefix{}
    50  	*dp2 = dp
    51  	return dp2
    52  }
    53  
    54  // number 123kb
    55  // symbolOrName is k or kilo
    56  func (dp *BinaryMultiplePrefix) SetPrefix(symbolOrName string) *BinaryMultiplePrefix {
    57  	for _, prefix := range binaryPositiveMultiplePrefixes {
    58  		if prefix.matched(symbolOrName) {
    59  			*dp = prefix
    60  			return dp
    61  		}
    62  	}
    63  	*dp = BinaryMultiplePrefixOne
    64  	return dp
    65  }
    66  
    67  // number 1000000 => power 6 => prefix M
    68  func (dp *BinaryMultiplePrefix) SetPower(power int) *BinaryMultiplePrefix {
    69  	if power == 0 {
    70  		*dp = BinaryMultiplePrefixOne
    71  		return dp
    72  	}
    73  	if power > 0 {
    74  		for _, prefix := range binaryPositiveMultiplePrefixes {
    75  			if prefix.power == power {
    76  				*dp = prefix
    77  				return dp
    78  			}
    79  		}
    80  		*dp = BinaryMultiplePrefixOne
    81  		return dp
    82  	}
    83  	*dp = BinaryMultiplePrefixOne
    84  	return dp
    85  }
    86  
    87  // number 1000000 => power 6 => prefix M
    88  func (dp *BinaryMultiplePrefix) SetUint64(num uint64) *BinaryMultiplePrefix {
    89  	return dp.SetFloat64(float64(num))
    90  }
    91  
    92  func (dp *BinaryMultiplePrefix) SetInt64(num int64) *BinaryMultiplePrefix {
    93  	if num >= 0 {
    94  		return dp.SetUint64(uint64(num))
    95  	}
    96  	return dp.SetUint64(uint64(-num))
    97  }
    98  
    99  func (dp *BinaryMultiplePrefix) SetFloat64(num float64) *BinaryMultiplePrefix {
   100  	if math_.Close(num, 0) {
   101  		*dp = BinaryMultiplePrefixOne
   102  		return dp
   103  	}
   104  	num = math.Abs(num)
   105  	if num > math.MaxUint64 {
   106  		*dp = BinaryMultiplePrefixMax
   107  		return dp
   108  	}
   109  
   110  	numPower := math.Log10(num) / math.Log10(float64(dp.Base()))
   111  	if math_.Close(numPower, 0) {
   112  		*dp = BinaryMultiplePrefixOne
   113  		return dp
   114  	}
   115  	if numPower > 0 {
   116  		// 幂
   117  		if numPower >= float64(BinaryMultiplePrefixMax.power) {
   118  			*dp = BinaryMultiplePrefixMax
   119  			return dp
   120  		}
   121  		lastPrefix := BinaryMultiplePrefixOne
   122  		for _, prefix := range binaryPositiveMultiplePrefixes {
   123  			if numPower < float64(prefix.power) {
   124  				*dp = lastPrefix
   125  				return dp
   126  			}
   127  			lastPrefix = prefix
   128  		}
   129  
   130  		*dp = BinaryMultiplePrefixMax
   131  		return dp
   132  	}
   133  	if numPower <= float64(BinaryMultiplePrefixMin.power) {
   134  		*dp = BinaryMultiplePrefixMin
   135  		return dp
   136  	}
   137  
   138  	*dp = BinaryMultiplePrefixMin
   139  	return dp
   140  }
   141  
   142  func (dp *BinaryMultiplePrefix) SetBigFloat(num *big.Float) *BinaryMultiplePrefix {
   143  	num.Abs(num)
   144  
   145  	if num.Cmp(big.NewFloat(math.MaxFloat64)) <= 0 {
   146  		f64, _ := num.Float64()
   147  		return dp.SetFloat64(f64)
   148  	}
   149  
   150  	*dp = BinaryMultiplePrefixMax
   151  	return dp
   152  }
   153  
   154  func (dp *BinaryMultiplePrefix) SetBigInt(num *big.Int) *BinaryMultiplePrefix {
   155  	var numFloat big.Float
   156  	numFloat.SetInt(num)
   157  	return dp.SetBigFloat(&numFloat)
   158  }
   159  
   160  func (dp *BinaryMultiplePrefix) SetBigRat(num *big.Rat) *BinaryMultiplePrefix {
   161  	var numFloat big.Float
   162  	numFloat.SetRat(num)
   163  	return dp.SetBigFloat(&numFloat)
   164  }