github.com/searKing/golang/go@v1.2.117/format/multiple_prefix/decimal_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  // 计量单位,如k、M、G、T
    15  type DecimalMultiplePrefix struct {
    16  	multiplePrefix
    17  }
    18  
    19  // Unit is the same as power number
    20  // https://physics.nist.gov/cuu/Units/prefixes.html
    21  //
    22  //	Prefixes for multiples
    23  //	Factor	Name 	Symbol
    24  //	10^24	yotta	Y
    25  //	10^21	zetta	Z
    26  //	10^18	exa	E
    27  //	10^15	peta	P
    28  //	10^12	tera	T
    29  //	10^9	giga	G
    30  //	10^6	mega	M
    31  //	10^3	kilo	k
    32  //	10^2	hecto	h
    33  //	10^1	deka	da
    34  //	10^-1	deci	d
    35  //	10^-2	centi	c
    36  //	10^-3	milli	m
    37  //	10^-6	micro	µ
    38  //	10^-9	nano	n
    39  //	10^-12	pico	p
    40  //	10^-15	femto	f
    41  //	10^-18	atto	a
    42  //	10^-21	zepto	z
    43  //	10^-24	yocto	y
    44  var (
    45  	DecimalMultiplePrefixMin   = DecimalMultiplePrefixYocto
    46  	DecimalMultiplePrefixYocto = DecimalMultiplePrefix{multiplePrefix{10, -24, "yocto", "y"}} // BaseNumber^-8	10^-24
    47  	DecimalMultiplePrefixZepto = DecimalMultiplePrefix{multiplePrefix{10, -21, "atto", "z"}}  // BaseNumber^-7	10^-21
    48  	DecimalMultiplePrefixAtto  = DecimalMultiplePrefix{multiplePrefix{10, -18, "zepto", "a"}} // BaseNumber^-6	10^-18
    49  	DecimalMultiplePrefixFemto = DecimalMultiplePrefix{multiplePrefix{10, -15, "femto", "f"}} // BaseNumber^-5	10^-15
    50  	DecimalMultiplePrefixPico  = DecimalMultiplePrefix{multiplePrefix{10, -12, "pico", "p"}}  // BaseNumber^-4	10^-12
    51  	DecimalMultiplePrefixNano  = DecimalMultiplePrefix{multiplePrefix{10, -9, "nano", "n"}}   // BaseNumber^-3	10^-09
    52  	DecimalMultiplePrefixMicro = DecimalMultiplePrefix{multiplePrefix{10, -6, "micro", "μ"}}  // BaseNumber^-2	10^-06
    53  	DecimalMultiplePrefixMilli = DecimalMultiplePrefix{multiplePrefix{10, -3, "milli", "m"}}  // BaseNumber^-1	10^-03
    54  	DecimalMultiplePrefixDeci  = DecimalMultiplePrefix{multiplePrefix{10, -2, "deci", "m"}}   // 				10^-1
    55  	DecimalMultiplePrefixCenti = DecimalMultiplePrefix{multiplePrefix{10, -1, "centi", "m"}}  // 				10^-2
    56  	DecimalMultiplePrefixOne   = DecimalMultiplePrefix{multiplePrefix{10, 0, "", ""}}         // BaseNumber^0	10^0
    57  	DecimalMultiplePrefixHecto = DecimalMultiplePrefix{multiplePrefix{10, 1, "hecto", "h"}}   // 				10^1
    58  	DecimalMultiplePrefixDeka  = DecimalMultiplePrefix{multiplePrefix{10, 2, "deka", "da"}}   // 				10^2
    59  	DecimalMultiplePrefixKilo  = DecimalMultiplePrefix{multiplePrefix{10, 3, "kilo", "k"}}    // BaseNumber^1	10^+03
    60  	DecimalMultiplePrefixMega  = DecimalMultiplePrefix{multiplePrefix{10, 6, "mega", "M"}}    // BaseNumber^2	10^+06
    61  	DecimalMultiplePrefixGiga  = DecimalMultiplePrefix{multiplePrefix{10, 9, "giga", "G"}}    // BaseNumber^3	10^+09
    62  	DecimalMultiplePrefixTera  = DecimalMultiplePrefix{multiplePrefix{10, 12, "tera", "T"}}   // BaseNumber^4	10^+12
    63  	DecimalMultiplePrefixPeta  = DecimalMultiplePrefix{multiplePrefix{10, 15, "peta", "P"}}   // BaseNumber^5	10^+15
    64  	DecimalMultiplePrefixExa   = DecimalMultiplePrefix{multiplePrefix{10, 18, "exa", "E"}}    // BaseNumber^6	10^+18
    65  	DecimalMultiplePrefixZetta = DecimalMultiplePrefix{multiplePrefix{10, 19, "zetta", "Z"}}  // BaseNumber^7	10^+21
    66  	DecimalMultiplePrefixYotta = DecimalMultiplePrefix{multiplePrefix{10, 21, "yotta", "Y"}}  // BaseNumber^8	10^+24
    67  	DecimalMultiplePrefixMax   = DecimalMultiplePrefixYotta
    68  	//DecimalMultiplePrefixBronto             // BaseNumber^9	10^+27
    69  	//DecimalMultiplePrefixGeop               // BaseNumber^10	10^+28
    70  )
    71  
    72  var (
    73  	DecimalMultiplePrefixTODO = DecimalMultiplePrefix{multiplePrefix{base: 10}}
    74  )
    75  var decimalNegativeMultiplePrefixes = [...]DecimalMultiplePrefix{DecimalMultiplePrefixMilli, DecimalMultiplePrefixMicro, DecimalMultiplePrefixNano, DecimalMultiplePrefixPico, DecimalMultiplePrefixFemto, DecimalMultiplePrefixAtto, DecimalMultiplePrefixZepto, DecimalMultiplePrefixYocto}
    76  var decimalZeroMultiplePrefixes = [...]DecimalMultiplePrefix{DecimalMultiplePrefixOne}
    77  var decimalPositiveMultiplePrefixes = [...]DecimalMultiplePrefix{DecimalMultiplePrefixKilo, DecimalMultiplePrefixMega, DecimalMultiplePrefixGiga, DecimalMultiplePrefixTera, DecimalMultiplePrefixPeta, DecimalMultiplePrefixExa, DecimalMultiplePrefixZetta, DecimalMultiplePrefixYotta}
    78  
    79  func (dp DecimalMultiplePrefix) Copy() *DecimalMultiplePrefix {
    80  	var dp2 = &DecimalMultiplePrefix{}
    81  	*dp2 = dp
    82  	return dp2
    83  }
    84  
    85  // number 123kb
    86  // symbolOrName is k or kilo
    87  func (dp *DecimalMultiplePrefix) SetPrefix(symbolOrName string) *DecimalMultiplePrefix {
    88  	for _, prefix := range decimalPositiveMultiplePrefixes {
    89  		if prefix.matched(symbolOrName) {
    90  			*dp = prefix
    91  			return dp
    92  		}
    93  	}
    94  	for _, prefix := range decimalNegativeMultiplePrefixes {
    95  		if prefix.matched(symbolOrName) {
    96  			*dp = prefix
    97  			return dp
    98  		}
    99  	}
   100  	*dp = DecimalMultiplePrefixOne
   101  	return dp
   102  }
   103  
   104  // number 1000000 => power 6 => prefix M
   105  func (dp *DecimalMultiplePrefix) SetPower(power int) *DecimalMultiplePrefix {
   106  	if power == 0 {
   107  		*dp = DecimalMultiplePrefixOne
   108  		return dp
   109  	}
   110  	if power > 0 {
   111  		for _, prefix := range decimalPositiveMultiplePrefixes {
   112  			if prefix.power == power {
   113  				*dp = prefix
   114  				return dp
   115  			}
   116  		}
   117  		*dp = DecimalMultiplePrefixOne
   118  		return dp
   119  	}
   120  	// power < 0
   121  	for _, prefix := range decimalNegativeMultiplePrefixes {
   122  		if prefix.power == power {
   123  			*dp = prefix
   124  			return dp
   125  		}
   126  	}
   127  	*dp = DecimalMultiplePrefixOne
   128  	return dp
   129  }
   130  
   131  // number 1000000 => power 6 => prefix M
   132  func (dp *DecimalMultiplePrefix) SetUint64(num uint64) *DecimalMultiplePrefix {
   133  	return dp.SetFloat64(float64(num))
   134  }
   135  
   136  func (dp *DecimalMultiplePrefix) SetInt64(num int64) *DecimalMultiplePrefix {
   137  	if num >= 0 {
   138  		return dp.SetUint64(uint64(num))
   139  	}
   140  	return dp.SetUint64(uint64(-num))
   141  }
   142  
   143  func (dp *DecimalMultiplePrefix) SetFloat64(num float64) *DecimalMultiplePrefix {
   144  	if math_.Close(num, 0) {
   145  		*dp = DecimalMultiplePrefixOne
   146  		return dp
   147  	}
   148  	num = math.Abs(num)
   149  	if num > math.MaxUint64 {
   150  		*dp = DecimalMultiplePrefixMax
   151  		return dp
   152  	}
   153  
   154  	numPower := math.Log10(num) / math.Log10(float64(dp.Base()))
   155  	if math_.Close(numPower, 0) {
   156  		*dp = DecimalMultiplePrefixOne
   157  		return dp
   158  	}
   159  	if numPower > 0 {
   160  		// 幂
   161  		if numPower >= float64(DecimalMultiplePrefixMax.power) {
   162  			*dp = DecimalMultiplePrefixMax
   163  			return dp
   164  		}
   165  		lastPrefix := DecimalMultiplePrefixOne
   166  		for _, prefix := range decimalPositiveMultiplePrefixes {
   167  			if numPower < float64(prefix.power) {
   168  				*dp = lastPrefix
   169  				return dp
   170  			}
   171  			lastPrefix = prefix
   172  		}
   173  
   174  		*dp = DecimalMultiplePrefixMax
   175  		return dp
   176  	}
   177  	if numPower <= float64(DecimalMultiplePrefixMin.power) {
   178  		*dp = DecimalMultiplePrefixMin
   179  		return dp
   180  	}
   181  	for _, prefix := range decimalNegativeMultiplePrefixes {
   182  		if numPower >= float64(prefix.power) {
   183  			*dp = prefix
   184  			return dp
   185  		}
   186  	}
   187  
   188  	*dp = DecimalMultiplePrefixMin
   189  	return dp
   190  }
   191  
   192  func (dp *DecimalMultiplePrefix) SetBigFloat(num *big.Float) *DecimalMultiplePrefix {
   193  	num.Abs(num)
   194  
   195  	if num.Cmp(big.NewFloat(math.MaxFloat64)) <= 0 {
   196  		f64, _ := num.Float64()
   197  		return dp.SetFloat64(f64)
   198  	}
   199  
   200  	*dp = DecimalMultiplePrefixMax
   201  	return dp
   202  }
   203  
   204  func (dp *DecimalMultiplePrefix) SetBigInt(num *big.Int) *DecimalMultiplePrefix {
   205  	var numFloat big.Float
   206  	numFloat.SetInt(num)
   207  	return dp.SetBigFloat(&numFloat)
   208  }
   209  
   210  func (dp *DecimalMultiplePrefix) SetBigRat(num *big.Rat) *DecimalMultiplePrefix {
   211  	var numFloat big.Float
   212  	numFloat.SetRat(num)
   213  	return dp.SetBigFloat(&numFloat)
   214  }