github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/units/main.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  )
     7  
     8  type Unit struct {
     9  	meter    int8
    10  	kilogram int8
    11  	second   int8
    12  	ampere   int8
    13  	kelvin   int8
    14  	mole     int8
    15  	candela  int8
    16  }
    17  
    18  var (
    19  	Scalar = Unit{0, 0, 0, 0, 0, 0, 0}
    20  	M      = Unit{1, 0, 0, 0, 0, 0, 0}
    21  	Kg     = Unit{0, 1, 0, 0, 0, 0, 0}
    22  	Sec    = Unit{0, 0, 1, 0, 0, 0, 0}
    23  
    24  	MetersPerSec = Unit{1, 0, -1, 0, 0, 0, 0}
    25  )
    26  
    27  func (a *Unit) Mul(b Unit) {
    28  	a.meter += b.meter
    29  	a.kilogram += b.kilogram
    30  	a.second += b.second
    31  	a.ampere += b.ampere
    32  	a.kelvin += b.kelvin
    33  	a.mole += b.mole
    34  	a.candela += b.candela
    35  }
    36  
    37  func (a *Unit) Div(b Unit) {
    38  	a.meter -= b.meter
    39  	a.kilogram -= b.kilogram
    40  	a.second -= b.second
    41  	a.ampere -= b.ampere
    42  	a.kelvin -= b.kelvin
    43  	a.mole -= b.mole
    44  	a.candela -= b.candela
    45  }
    46  
    47  func (u *Unit) String() string {
    48  	var b bytes.Buffer
    49  	a := func(prefix string, v int8) {
    50  		if v != 0 {
    51  			b.WriteString(fmt.Sprintf("%s^%d", prefix, v))
    52  		}
    53  	}
    54  	a("m", u.meter)
    55  	a("kg", u.kilogram)
    56  	a("s", u.second)
    57  
    58  	a("A", u.ampere)
    59  	a("K", u.kelvin)
    60  	a("mol", u.mole)
    61  	a("cd", u.candela)
    62  	return b.String()
    63  }
    64  
    65  type V struct {
    66  	Value float64
    67  	Unit  Unit
    68  }
    69  
    70  func (a V) Add(b V) V {
    71  	if a.Unit != b.Unit {
    72  		panic("Incompatible units")
    73  	}
    74  	r := a
    75  	r.Value += b.Value
    76  	return r
    77  }
    78  
    79  func (a V) Sub(b V) V {
    80  	if a.Unit != b.Unit {
    81  		panic("Incompatible units")
    82  	}
    83  	r := a
    84  	r.Value -= b.Value
    85  	return r
    86  }
    87  
    88  func (a V) Mul(b V) V {
    89  	r := a
    90  	r.Unit.Mul(b.Unit)
    91  	r.Value *= b.Value
    92  	return r
    93  }
    94  
    95  func (a V) Div(b V) V {
    96  	r := a
    97  	r.Unit.Div(b.Unit)
    98  	r.Value /= b.Value
    99  	return r
   100  }
   101  
   102  func (a V) String() string {
   103  	return fmt.Sprintf("%f[%s]", a.Value, a.Unit.String())
   104  }
   105  
   106  func main() {
   107  	a := V{3, Kg}
   108  	a.Unit.kilogram = 1
   109  
   110  	b := V{2, Sec}
   111  
   112  	r := a.Div(b)
   113  	fmt.Printf("%v\n", r)
   114  	r = r.Div(b)
   115  	fmt.Printf("%v\n", r)
   116  
   117  	v := r.Add(b)
   118  	fmt.Printf("%v\n", v)
   119  }