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