Object
This class represents a Unit. A Unit uses a given Converter with a number of registered units in which it can be expressed. A Unit is the product of the powers of other units. In principle, these need not be integer powers, but this may cause problems with rounding. The following code for example returns false:
Unit.new(:m => 0.1) * Unit.new(:m => 0.2) == Unit.new(:m => 0.3)
Units can be multiplied, divided, and raised to a given power. As an extra, 1 can be divided by a Unit.
Examples:
Unit.new(:mi => 1, :s => -1) ** 2 # => mi**2/s**2 Unit.new(:mi => 1, :s => -1) * Unit.new(:s => 1, :usd => -1) # => mi/usd Unit.new(:mi => 1, :s => -1, Converter.converter(:uk)) * Unit.new(:s => 1, :usd => -1, Converter.converter(:us)) # => TypeError 1 / Unit.new(:mi => 1, :s => -1) # => s/mi
Creates a new (composite) Unit. It is passed a hash of the form {:unit => exponent}, and the Converter to use.
Examples:
Unit.new(:m => 1, :s => -1, Converter.converter(:uk)) # => m/s Unit.new(:mi => 1, :s => -2) # => mi/s**2
See also Converter, Converter.converter
# File lib/van/units/base.rb, line 206 206: def initialize(units = {}, converter = nil) 207: conv = proc { converter ||= Units::Converter.current } 208: if units.is_a? ::String 209: @units = decode_string(units, conv) 210: else 211: @units = {} 212: units.each_pair do |k, v| 213: k = conv[].base_unit(k.to_sym) if not k.is_a? Units::BaseUnit 214: @units[k] = v 215: end 216: end 217: normalize_units 218: end
Multiplies with the given Unit.
# File lib/van/units/base.rb, line 230 230: def *(other) 231: do_op(:*, :+, other) 232: end
Raises to the given power.
# File lib/van/units/base.rb, line 221 221: def **(p) 222: result = {} 223: @units.each_pair do |u, e| 224: result[u] = e * p 225: end 226: Units::Unit.new(result) 227: end
Divides by the given Unit.
# File lib/van/units/base.rb, line 235 235: def /(other) 236: do_op(:/, :-, other) 237: end
Returns true iff the two units are equals, i.e., iff they have the same exponent for all units, and they both use the same Converter.
# File lib/van/units/base.rb, line 255 255: def ==(other) 256: other.is_a?(Units::Unit) && other.units == units 257: end
Returns true iff this Unit is compatible with the given Unit. This is less strict than equality because for example hours are compatible with seconds (“we can add them”), but hours are not seconds.
# File lib/van/units/base.rb, line 268 268: def compatible_with?(other) 269: conv1, conv2 = Units::Converter.coerce_units(self, other) 270: conv1.units == conv2.units 271: end
# File lib/van/units/base.rb, line 261 261: def hash 262: @units.to_a.map { |e| e.hash }.hash 263: end
# File lib/van/units/base.rb, line 291 291: def method_missing(m, *args, &blk) 292: if args.length == 1 293: args[0] = (Units::Converter.converter(args[0]) rescue nil) if not args[0].is_a? Units::Converter 294: return self * Units::Unit.new({m => 1}, args[0]) if args[0] && args[0].registered?(m) 295: elsif (Units::Converter.current.registered?(m) rescue false) 296: raise ::ArgumentError, "Wrong number of arguments" if args.length != 0 297: return self * Units::Unit.new({m => 1}, Units::Converter.current) 298: end 299: ::Exception.with_clean_backtrace("method_missing") { 300: super 301: } 302: end
# File lib/van/units/base.rb, line 249 249: def simplify 250: Units::Converter.simplify_unit(self) 251: end
Returns a human readable string representation.
# File lib/van/units/base.rb, line 274 274: def to_s 275: numerator = "" 276: denominator = "" 277: @units.each_pair do |u, e| 278: e_abs = e > 0 ? e : -e # This works with Complex too 279: (e > 0 ? numerator : denominator) << " #{u.to_s}#{"**#{e_abs}" if e_abs != 1}" 280: end 281: "#{numerator.lstrip}#{"/" + denominator.lstrip if not denominator.empty?}" 282: end
Returns self.
# File lib/van/units/base.rb, line 285 285: def to_unit(converter = nil) 286: self 287: end
Returns true iff this Unit has all exponents equal to 0.
# File lib/van/units/base.rb, line 240 240: def unitless? 241: @units.empty? 242: end
# File lib/van/units/base.rb, line 320 320: def decode_multiplicative_string(s, multiplier, converter, result) 321: s.scan(Units::Regexps::SINGLE_UNIT_REGEXP) do |conv, unit, exp| 322: if unit 323: conv = Units::Converter.converter(conv) 324: else 325: conv, unit = converter[], conv 326: end 327: exp ||= '1' 328: unit = conv.base_unit(unit) 329: result[unit] = (result[unit] || 0) + Integer(exp) * multiplier 330: end 331: end
# File lib/van/units/base.rb, line 306 306: def decode_string(s, converter) 307: if Units::Regexps::TOTAL_UNIT_REGEXP =~ s 308: numerator, denominator = $1, $2 309: units = {} 310: decode_multiplicative_string(numerator, 1, converter, units) if numerator 311: decode_multiplicative_string(denominator, 1, converter, units) if denominator 312: units 313: elsif /^\s*$/ =~ s 314: {} 315: else 316: raise ::ArgumentError, "Illegal unit string #{s.dump}" 317: end 318: end
# File lib/van/units/base.rb, line 339 339: def do_op(op, dual_op, other) 340: other = other.to_unit 341: raise TypeError, "cannot convert to Unit" unless Units::Unit === other 342: result = @units.dup 343: other.units.each_pair do |u, e| 344: result[u] = 0 if not result[u] 345: result[u] = result[u].send(dual_op, e) 346: end 347: Units::Unit.new(result) 348: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.