This class represents a Value with a numeric value and a Unit. The numeric value can be any Numeric, though it is not recommended to use Values.
A Value can be added to, subtracted from and multiplied with another value, though only when both Values are using the same Converter. While multiplication is always possible, adding or subtracting values with incompatible units results in a TypeError. When two units are compatible but not the same, the Value with the larger of the units is converted to the smaller of the units. For example adding 100 seconds and 1 minute, the latter is converted to 60 seconds because a second is smaller than a minute. The result is 160 seconds.
Creates a new Value with the given numeric value and the given unit. Simply returns the given value if the given unit is unitless, i.e., when unit.unitless? is true.
# File lib/van/units/base.rb, line 381
381: def new(value, *args)
382: res = new!(value, *args)
383: return res.value if res.unit.unitless?
384: res
385: end
# File lib/van/units/base.rb, line 387
387: def new!(value, *args)
388: if ::String === value
389: str = *args
390: converter = case args.length
391: when 0
392: when 1
393: conv = args[0]
394: else
395: raise ArgumentError, "wrong number of arguments"
396: end
397: value, unit = decode_string(value, converter)
398: else
399: if args.length == 1
400: unit = args[0]
401: else
402: raise ArgumentError, "wrong number of arguments"
403: end
404: end
405: unit = Unit.new(unit) unless unit.is_a?(Unit)
406: old_new(value, unit)
407: end
# File lib/van/units/base.rb, line 577
577: def self.decode_string(s, converter)
578: if m = Units::Regexps::VALUE_REGEXP.match(s)
579: value = m[2].empty? ? Integer(m[1]) : Float(m[1])
580: unit = Units::Unit.new(m[3], converter)
581: [value, unit]
582: else
583: raise ::ArgumentError, "Illegal value string #{s.dump}"
584: end
585: end
# File lib/van/units/base.rb, line 436
436: def div(other)
437: do_additive_op(:div, other)[0]
438: end
# File lib/van/units/base.rb, line 431
431: def divmod(other)
432: (q, r), unit = *do_additive_op(:divmod, other)
433: [q, Units::Value.new(r, unit)]
434: end
# File lib/van/units/base.rb, line 464
464: def hash
465: @value.hash ^ @unit.hash
466: end
# File lib/van/units/base.rb, line 562
562: def method_missing(m, *args, &blk)
563: if args.length == 1
564: args[0] = (Units::Converter.converter(args[0]) rescue nil) if not args[0].is_a? Units::Converter
565: return self * Units::Value.new(1, Units::Unit.new({m => 1}, args[0])) if args[0] && args[0].registered?(m)
566: elsif (Units::Converter.current.registered?(m) rescue false)
567: raise ::ArgumentError, "Wrong number of arguments" if args.length != 0
568: return self * Units::Value.new(1, Units::Unit.new({m => 1}, Units::Converter.current))
569: end
570: ::Exception.with_clean_backtrace("method_missing") {
571: super
572: }
573: end
Converts this Value to the given Unit. This only works if the Converters used by this Value’s Unit and the given Unit are the same. It obviously fails if the Units are not compatible (can’t add apples and oranges).
# File lib/van/units/base.rb, line 488
488: def to(to_unit, converter = nil)
489: raise ArgumentError, "Wrong number of arguments" if converter && !(::String === to_unit)
490: to_unit = to_unit.to_unit(converter)
491: raise TypeError, "cannot convert to Unit" unless Units::Unit === to_unit
492: conv1, conv2 = unit.coerce(to_unit)
493: raise TypeError, "incompatible units for operation" if conv1.units != conv2.units
494: mult = conv1.multiplier / conv2.multiplier
495: Units::Value.new(value * mult, to_unit)
496: end
Returns a float if this Value is unitless, and raises an exception otherwise.
# File lib/van/units/base.rb, line 513
513: def to_f
514: val = simplify
515: if Units::Value === val
516: raise TypeError, "Cannot convert to float"
517: else
518: val.to_f
519: end
520: end
Returns an int if this Value is unitless, and raises an exception otherwise.
# File lib/van/units/base.rb, line 524
524: def to_i
525: val = simplify
526: if Units::Value === val
527: raise TypeError, "Cannot convert to integer"
528: else
529: val.to_i
530: end
531: end
Returns an int if this Value is unitless, and raises an exception otherwise.
# File lib/van/units/base.rb, line 535
535: def to_int
536: val = simplify
537: if Units::Value === val
538: raise TypeError, "Cannot convert to integer"
539: else
540: val.to_int
541: end
542: end
Returns a human readable string representation.
# File lib/van/units/base.rb, line 507
507: def to_s
508: "#{@value} #{@unit}"
509: end
# File lib/van/units/base.rb, line 587
587: def do_additive_op(op, other)
588: other = other.to_value
589: raise TypeError, "cannot convert to Value" unless Units::Value === other
590: if other.is_a? Units::Value
591: conv1, conv2 = unit.coerce(other.unit)
592: raise TypeError, "incompatible units for #{op}" if conv1.units != conv2.units
593: mult = conv2.multiplier / conv1.multiplier
594: if mult > 1
595: [value.send(op, other.value * mult), unit]
596: else
597: mult = conv1.multiplier / conv2.multiplier
598: [(value * mult).send(op, other.value), other.unit]
599: end
600: else
601: raise TypeError, "incompatible operands for #{op}"
602: end
603: end
# File lib/van/units/base.rb, line 605
605: def do_multiplicative_op(op, other)
606: case other
607: when Units::Value
608: [value.send(op, other.value), unit.send(op, other.unit)]
609: when Units::Unit
610: [value, unit.send(op, other)]
611: when ::Numeric
612: [value.send(op, other), unit]
613: else
614: # TODO: How to make this work for Units as well?
615: # Problem : how check whether to_value failed without
616: # masking all exceptions?
617: other = other.to_value
618: raise TypeError, "cannot convert to Value" unless Units::Value === other
619: do_multiplicative_op(op, other)
620: end
621: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.