From: Mathieu Bouchard Date: 2001-03-19T02:00:43+09:00 Subject: [ruby-talk:12821] units of measure This is something i wrote a month ago. I'm not doing anything with it for now, so I post it in case someone wants to pick it up. It's a system so that units of measure can be computed together (class Unit) and so that numeric values can be attached units (class Quantity) # Copyright 2001 by Mathieu Bouchard # Licensed under the same terms as Ruby class Unit attr_reader :table def initialize(h) @table = h.dup @table.delete_if {|x| x==0 } end def to_s t = @table.keys.sort {|a,b| @table[a] <=> @table[b] } t1,t2 = t.find_all {|x| @table[x] > 0 }, t.find_all {|x| @table[x] < 0 } t1,t2=[t1,t2].map {|ti| ti.map {|x| y=@table[x].abs y==1? "#{x}" : "#{x}^#{y.abs}" }.join('.') } t1='1' if t1.length==0 return t1 if t2.length==0 [t1,t2].join '/' end def inspect; to_s; end def +(other) h = @table.dup other.table.each {|k,v| h[k]||=0; h[k]+=v } Unit.new h end def -@ h = @table.dup h.each {|k,v| h[k]=-v } Unit.new h end def -(other); self+-other; end end class Quantity attr_reader :value attr_reader :unit def initialize(value,unit) @value = value @unit = unit end def +(other) self.unit == other.unit or raise TypeError Quantity.new(self.value + other.value, self.unit) end def -@; Quantity.new(-self.value, self.unit); end def *(other) Quantity.new(self.value * other.value, self.unit + other.unit) end def /(other) Quantity.new(self.value / other.value, self.unit - other.unit) end def to_s [value,unit].join " " end def inspect; to_s; end end $u = Unit.new 'm'=>1,'s'=>-2; p $u $v = Unit.new 'kg'=>1,'m'=>1; p $v $w = $u+$v; p $w p -$w #=> m/s^2 #=> m.kg #=> kg.m^2/s^2 #=> s^2/m^2.kg $a = Quantity.new 9.8, $u; p $a $b = Quantity.new 8888, Unit.new('m'=>1); p $b $c = $a*$b*Quantity.new(42, Unit.new 'kg'=>1); p $c p ($a*$a/$c) # lol #=> 9.8 m/s^2 #=> 8888 m #=> 3658300.8 kg.m^2/s^2 #=> 2.625262526e-05 1/s^2.kg