Class: Quantity::Unit
- Inherits:
-
Object
- Object
- Quantity::Unit
- Includes:
- Comparable
- Defined in:
- lib/quantity/unit.rb,
lib/quantity/systems/si.rb,
lib/quantity/systems/us.rb,
lib/quantity/systems/imperial.rb,
lib/quantity/systems/enumerable.rb,
lib/quantity/systems/information.rb
Overview
Imperial versions of british/american customary units
Constant Summary collapse
- @@units =
All known units
{}
Instance Attribute Summary collapse
-
#aliases ⇒ Object
readonly
Instance-level methods/vars.
-
#dimension ⇒ Object
readonly
Instance-level methods/vars.
-
#name ⇒ Object
readonly
Instance-level methods/vars.
-
#units ⇒ Object
readonly
Higher-order units have a set of units to reference each aspect of the dimension they measure.
-
#value ⇒ Object
readonly
Instance-level methods/vars.
Class Method Summary collapse
-
.add_alias(unit, *names) ⇒ Object
Register a unit with the given symbols.
-
.add_unit(name, dimension, value, *names) ⇒ Object
(also: add)
Add a unit to the system.
-
.add_units(&block) ⇒ Object
Add a number of units to the system.
-
.for(to) ⇒ Unit
The unit for a given symbol or string description of a compound unit.
-
.from_string_form(to) ⇒ Object
Parse a string representation of a unit, such as foot^2/time^2, and return a compound object representing it.
-
.is_unit?(to) ⇒ Boolean
Whether or not the given symbol or string refers to an existing unit.
-
.string_form(dimension, units) ⇒ String
a vaguely human-readable format for a compound unit.
Instance Method Summary collapse
-
#*(other) ⇒ Unit
Unit multiplication.
-
#**(other) ⇒ Unit
Exponentiation.
-
#/(other) ⇒ Unit
Unit division.
- #<=>(other) ⇒ Object
- #bit ⇒ Object
-
#calculate_value ⇒ Object
calculate this unit's value compared to the reference unit.
-
#can_convert_to?(to) ⇒ Boolean
Can this unit be converted into the target unit?.
-
#convert(target) ⇒ Unit
Convert a portion of this compound to another unit.
-
#convert_proc(to) ⇒ Unit
Return a proc that will perform conversion from this unit to the given one.
-
#initialize(opts = {}) ⇒ Unit
constructor
A new compound unit.
- #inspect ⇒ Object
-
#names ⇒ [Symbol String]
All the known aliases for this Unit, i.e.
-
#reduced_name ⇒ Object
A reduced form of this unit.
-
#s_for(value) ⇒ String
A string representation of this unit at the given value.
-
#string_form ⇒ String
A vaguely human-readable form for this unit.
-
#value_for(reference_value) ⇒ Numeric
The value for a given reference value.
Constructor Details
#initialize(opts = {}) ⇒ Unit
A new compound unit. There are two modes of operation. One provides a way to add units with a DSL. The other provides an options hash a little better for programming. The last provides a way to create a unit for a given dimension--useful for reference units.
276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
# File 'lib/quantity/unit.rb', line 276 def initialize(opts) @units = opts[:units] @dimension = opts[:dimension] @value = opts[:value] || calculate_value if @dimension.nil? raise ArgumentError, "Adding invalid unit with nil dimension (#{name} - #{dimension})" end unless opts[:name] || !@dimension.is_base? raise ArgumentError, "Single-order units must be uniquely named (#{name} - #{dimension})" end @name = opts[:name] || string_form self.class.add_alias(self,@name.to_sym) raise ArgumentError, "Creating new unit with no value" unless @value end |
Instance Attribute Details
#aliases ⇒ Object (readonly)
Instance-level methods/vars
86 87 88 |
# File 'lib/quantity/unit.rb', line 86 def aliases @aliases end |
#dimension ⇒ Object (readonly)
Instance-level methods/vars
86 87 88 |
# File 'lib/quantity/unit.rb', line 86 def dimension @dimension end |
#name ⇒ Object (readonly)
Instance-level methods/vars
86 87 88 |
# File 'lib/quantity/unit.rb', line 86 def name @name end |
#units ⇒ Object (readonly)
Higher-order units have a set of units to reference each aspect of the dimension they measure. This is unused in basic units.
265 266 267 |
# File 'lib/quantity/unit.rb', line 265 def units @units end |
#value ⇒ Object (readonly)
Instance-level methods/vars
86 87 88 |
# File 'lib/quantity/unit.rb', line 86 def value @value end |
Class Method Details
.add_alias(unit, *names) ⇒ Object
Register a unit with the given symbols
48 49 50 51 52 53 |
# File 'lib/quantity/unit.rb', line 48 def self.add_alias(unit,*names) unit = Unit.for(unit) unless unit.is_a? Unit names.each do |name| @@units[name] = unit end end |
.add_unit(name, dimension, value, *names) ⇒ Object Also known as: add
Add a unit to the system
60 61 62 63 64 65 |
# File 'lib/quantity/unit.rb', line 60 def self.add_unit(name,dimension,value,*names) new_unit = Unit.new({ :name => name,:dimension => Quantity::Dimension.for(dimension),:value => value}) names.each do | name | add_alias new_unit, name end end |
.add_units(&block) ⇒ Object
Add a number of units to the system
75 76 77 |
# File 'lib/quantity/unit.rb', line 75 def self.add_units(&block) self.class_eval(&block) end |
.for(to) ⇒ Unit
The unit for a given symbol or string description of a compound unit
34 35 36 |
# File 'lib/quantity/unit.rb', line 34 def self.for(to) to.is_a?(Unit) ? to : @@units[to] end |
.from_string_form(to) ⇒ Object
Parse a string representation of a unit, such as foot^2/time^2, and return a compound object representing it.
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/quantity/unit.rb', line 242 def self.from_string_form(to) if Unit.for(to) Unit.for(to) else dimension_string = to.to_s.dup units = {} to.to_s.split(/(\^|\/|\*)/).each do | name | next if name =~ /(\^|\/|\*)/ || name =~ /^\d$/ unit = Unit.for(name.to_sym) || Unit.for(name) dimension_string.gsub!(name,unit.dimension.name.to_s) units[unit.dimension] = unit end dimension = Dimension.for(dimension_string.to_sym) raise ArgumentError, "Couldn't create Unit for #{to}" unless dimension && units unit = Unit.new({ :dimension => dimension, :units => units }) add_alias(unit,unit.name.to_sym) unit end end |
.is_unit?(to) ⇒ Boolean
Whether or not the given symbol or string refers to an existing unit
41 42 43 |
# File 'lib/quantity/unit.rb', line 41 def self.is_unit?(to) to.is_a?(Unit) || @@units.has_key?(to) end |
.string_form(dimension, units) ⇒ String
a vaguely human-readable format for a compound unit
318 319 320 321 322 323 324 |
# File 'lib/quantity/unit.rb', line 318 def self.string_form(dimension,units) string = dimension.string_form units.each do | dimension, unit | string = string.gsub(dimension.name.to_s, unit.name.to_s) end string end |
Instance Method Details
#*(other) ⇒ Unit
Unit multiplication.
192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/quantity/unit.rb', line 192 def *(other) if other.is_a?(Unit) units = other.units || { other.dimension => other } units.merge!(@units || { @dimension => self }) dim = @dimension * other.dimension existing = Unit.for(Unit.string_form(dim,units).to_sym) existing ||= Unit.new({ :dimension => dim, :units => units }) else raise ArgumentError, "Cannot multiply #{self} with #{other}" end end |
#**(other) ⇒ Unit
Exponentiation
181 182 183 184 185 186 187 |
# File 'lib/quantity/unit.rb', line 181 def **(other) if other.is_a?(Fixnum) && other > 0 other == 1 ? self : self * self**(other-1) else raise ArgumentError, "#{self} cannot be raised to #{other} power." end end |
#/(other) ⇒ Unit
Unit division.
207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/quantity/unit.rb', line 207 def /(other) if other.is_a?(Unit) units = other.units || { other.dimension => other } units.merge!(@units || { @dimension => self }) dim = @dimension / other.dimension existing = Unit.for(Unit.string_form(dim,units).to_sym) existing ||= Unit.new({ :dimension => dim, :units => units }) existing else raise ArgumentError, "Cannot multiply #{self} with #{other}" end end |
#<=>(other) ⇒ Object
168 169 170 171 172 173 174 175 176 |
# File 'lib/quantity/unit.rb', line 168 def <=>(other) if other.is_a?(Unit) && other.dimension == @dimension @value <=> other.value elsif other.is_a?(Unit) @name <=> other.name else nil end end |
#bit ⇒ Object
7 |
# File 'lib/quantity/systems/information.rb', line 7 add_unit :bit, :data, 1, :bits |
#calculate_value ⇒ Object
calculate this unit's value compared to the reference unit
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
# File 'lib/quantity/unit.rb', line 292 def calculate_value value = defined?(Rational) ? Rational(1) : 1.0 @dimension.numerators.each do | component | component.power.times do # we might have a unit for a compound dimension, such as liters for length^3. value *= @units[Quantity::Dimension.for(component.dimension)].value end end @dimension.denominators.each do | component | component.power.times do value /= @units[Quantity::Dimension.for(component.dimension)].value end end @value = value end |
#can_convert_to?(to) ⇒ Boolean
Can this unit be converted into the target unit?
102 103 104 |
# File 'lib/quantity/unit.rb', line 102 def can_convert_to?(to) Unit.for(to).dimension == @dimension end |
#convert(target) ⇒ Unit
Convert a portion of this compound to another unit. This one is tricky, because a lot of things can be happening. It's valid to convert m^2 to ft^2 and to feet (ft^2), but not really valid to convert to ft^3.
111 112 113 |
# File 'lib/quantity/unit.rb', line 111 def convert(to) Unit.for(to) end |
#convert_proc(to) ⇒ Unit
Return a proc that will perform conversion from this unit to the given one
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/quantity/unit.rb', line 118 def convert_proc(to) to = convert(to) #to = Unit.for(to) raise ArgumentError, "Unable to find unit #{to}" unless to unless (to.dimension == self.dimension) raise ArgumentError, "Cannot convert #{self.dimension} to #{to.dimension}" end if defined?(Rational) && (@value.is_a?(Fixnum)) && (to.value.is_a?(Fixnum)) lambda do | from | from * Rational(@value, to.value) end elsif defined?(Rational) && (@value.is_a?(Rational)) && (to.value.is_a?(Rational)) lambda do | from | from * @value / to.value end else lambda do | from | from * (@value / to.value.to_f) end end end |
#inspect ⇒ Object
163 164 165 166 |
# File 'lib/quantity/unit.rb', line 163 def inspect sprintf('#<%s:0x%s @name=%s @value=%s @dimension=%s>', self.class.name, self.__id__.to_s(16), @name.inspect, @value.inspect, @dimension.inspect) end |
#names ⇒ [Symbol String]
All the known aliases for this Unit, i.e. name + aliases
90 91 92 |
# File 'lib/quantity/unit.rb', line 90 def names [@name] + @aliases end |
#reduced_name ⇒ Object
A reduced form of this unit
95 96 97 |
# File 'lib/quantity/unit.rb', line 95 def reduced_name to_string_form.to_sym end |
#s_for(value) ⇒ String
A string representation of this unit at the given value
159 160 161 |
# File 'lib/quantity/unit.rb', line 159 def s_for(value) "#{value} #{@name.to_s}" end |
#string_form ⇒ String
A vaguely human-readable form for this unit
310 311 312 |
# File 'lib/quantity/unit.rb', line 310 def string_form self.class.string_form(@dimension,@units) end |
#value_for(reference_value) ⇒ Numeric
The value for a given reference value.
146 147 148 149 150 151 152 153 154 |
# File 'lib/quantity/unit.rb', line 146 def value_for(reference_value) if defined?(Rational) && (reference_value.is_a?(Fixnum)) && (@value.is_a?(Fixnum)) Rational(reference_value, @value) elsif defined?(Rational) && (reference_value.is_a?(Rational) || reference_value.is_a?(Fixnum)) && (@value.is_a?(Rational)) reference_value / @value #Rational(reference_value, @value) else reference_value / @value.to_f end end |