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 }