Class: Quantify::Quantity

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/quantify/quantity.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value, unit) ⇒ Quantity

Initialize a new Quantity object. Two arguments are required: a value and a unit. The unit can be a an instance of Unit::Base or the name, symbol or JScience label of a known (or derivable through know units and prefixes) unit



87
88
89
90
# File 'lib/quantify/quantity.rb', line 87

def initialize(value, unit)
  @value = value.to_f
  @unit = Unit.for(unit)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object (protected)

Dynamic method for converting to another unit, e.g

2.ft.to_metre.to_s                           #=> "0.6096 m"

30.degree_celsius.to_K.to_s :name            #=> "303.15 kelvins"


354
355
356
357
358
359
360
# File 'lib/quantify/quantity.rb', line 354

def method_missing(method, *args, &block)
  if method.to_s =~ /(to_)(.*)/
    to($2)
  else
    super
  end
end

Instance Attribute Details

#unitObject

Returns the value of attribute unit.



81
82
83
# File 'lib/quantify/quantity.rb', line 81

def unit
  @unit
end

#valueObject

Returns the value of attribute value.



81
82
83
# File 'lib/quantify/quantity.rb', line 81

def value
  @value
end

Class Method Details

.configure(&block) ⇒ Object



66
67
68
# File 'lib/quantify/quantity.rb', line 66

def self.configure(&block)
  self.class_eval(&block) if block
end

.parse(string) ⇒ Object

Parse a string and return a Quantity object based upon the value and subseqent unit name, symbol or JScience label. Returns an array containing quantity objects for each quantity recognised.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/quantify/quantity.rb', line 47

def self.parse(string)
  words = string.words
  quantities = words.each_with_index.map do |word,index|
    if word.starts_with_number?
      # Isolate number from subsequent string
      value, string = word, words[index+1..-1].join(" ")
      # Shift any trailing non-numeric characters to start of string.
      value, string = $1, "#{$2} #{string}" if (Unit::QUANTITY_REGEX).match(word)
      # Parse string for unit references
      unit = Unit.parse(string, :iterative => true) || Unit.dimensionless
      # Instantiate quantity using value and unit
      Quantity.new(value,unit)
    end
  end.compact
  return quantities
rescue Quantify::Exceptions::InvalidArgumentError
  raise Quantify::Exceptions::QuantityParseError, "Cannot parse string into value and unit"
end

Instance Method Details

#<=>(other) ⇒ Object



245
246
247
248
249
250
# File 'lib/quantify/quantity.rb', line 245

def <=>(other)
  raise Exceptions::InvalidArgumentError unless other.is_a? Quantity
  raise Exceptions::InvalidArgumentError unless other.unit.is_alternative_for?(unit)
  other = other.to @unit
  @value.to_f <=> other.value.to_f
end

#===(range) ⇒ Object



252
253
254
255
# File 'lib/quantify/quantity.rb', line 252

def ===(range)
  raise Exceptions::InvalidArgumentError unless range.is_a? Range
  range.cover? self
end

#add(other) ⇒ Object Also known as: +



184
185
186
# File 'lib/quantify/quantity.rb', line 184

def add(other)
  Quantity.new(@value,@unit).add!(other)
end

#add!(other) ⇒ Object



168
169
170
# File 'lib/quantify/quantity.rb', line 168

def add!(other)
  add_or_subtract!(:+, other)
end

#cancel_base_units!(*units) ⇒ Object



222
223
224
225
# File 'lib/quantify/quantity.rb', line 222

def cancel_base_units!(*units)
  @unit = @unit.cancel_base_units!(*units) if @unit.is_compound_unit?
  return self
end

#divide(other) ⇒ Object Also known as: /



200
201
202
# File 'lib/quantify/quantity.rb', line 200

def divide(other)
  Quantity.new(@value,@unit).divide!(other)
end

#divide!(other) ⇒ Object



180
181
182
# File 'lib/quantify/quantity.rb', line 180

def divide!(other)
  multiply_or_divide!(:/, other)
end

#inspectObject



119
120
121
# File 'lib/quantify/quantity.rb', line 119

def inspect
  to_s
end

#multiply(other) ⇒ Object Also known as: times, *



194
195
196
# File 'lib/quantify/quantity.rb', line 194

def multiply(other)
  Quantity.new(@value,@unit).multiply!(other)
end

#multiply!(other) ⇒ Object



176
177
178
# File 'lib/quantify/quantity.rb', line 176

def multiply!(other)
  multiply_or_divide!(:*, other)
end

#pow(power) ⇒ Object Also known as: **



205
206
207
# File 'lib/quantify/quantity.rb', line 205

def pow(power)
  Quantity.new(@value,@unit).pow!(power)
end

#pow!(power) ⇒ Object



161
162
163
164
165
166
# File 'lib/quantify/quantity.rb', line 161

def pow!(power)
  raise Exceptions::InvalidArgumentError, "Argument must be an integer" unless power.is_a? Integer
  @value = @value ** power
  @unit = @unit ** power
  return self
end

#rationalize_unitsObject



210
211
212
213
# File 'lib/quantify/quantity.rb', line 210

def rationalize_units
  return self unless @unit.is_a? Unit::Compound
  self.to @unit.clone.rationalize_base_units!
end

#rationalize_units!Object



215
216
217
218
219
220
# File 'lib/quantify/quantity.rb', line 215

def rationalize_units!
  rationalized_quantity = self.rationalize_units
  @value = rationalized_quantity.value
  @unit = rationalized_quantity.unit
  return self
end

#representsObject

Returns a description of what the quantity describes, based upon the physica quantity which is represented by the Dimensions object in the Quantity unit. e.g.

Quantity.parse("25 yr").represents            #=> :time

1.foot.represents                             #=> :length

Quantity.new(123.456, :degree_celsius).represents
                                              #=> :temperature


102
103
104
# File 'lib/quantify/quantity.rb', line 102

def represents
  @unit.measures
end

#round(decimal_places = 0) ⇒ Object

Similar to #round! but returns new Quantity instance rather than rounding in place



240
241
242
243
# File 'lib/quantify/quantity.rb', line 240

def round(decimal_places=0)
  rounded_quantity = Quantity.new @value, @unit
  rounded_quantity.round! decimal_places
end

#round!(decimal_places = 0) ⇒ Object

Round the value attribute to the specified number of decimal places. If no argument is given, the value is rounded to NO decimal places, i.e. to an integer



231
232
233
234
235
# File 'lib/quantify/quantity.rb', line 231

def round!(decimal_places=0)
  factor = ( decimal_places == 0 ? 1 : 10.0 ** decimal_places )
  @value = (@value * factor).round / factor
  self
end

#subtract(other) ⇒ Object Also known as: -



189
190
191
# File 'lib/quantify/quantity.rb', line 189

def subtract(other)
  Quantity.new(@value,@unit).subtract!(other)
end

#subtract!(other) ⇒ Object



172
173
174
# File 'lib/quantify/quantity.rb', line 172

def subtract!(other)
  add_or_subtract!(:-, other)
end

#to(new_unit) ⇒ Object

Converts self into a quantity using the unit provided as an argument. The new unit must represent the same physical quantity, i.e. have the same dimensions, e.g.

Quantity.parse("12 yd").to(:foot).to_s          #=> "36 ft"

1000.kilogram.to(:tonne).to_s                   #=> "1 t"

The method #method_missing provides some syntactic sugar for the new unit to be provided as part of the method name, based around /to_(<unit>)/, e.g.

200.cm.to_metre.to_s                   #=> "1 t"

The unit value is converted to the corresponding value for the same quantity in terms of the new unit.



139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/quantify/quantity.rb', line 139

def to(new_unit)
  new_unit = Unit.for new_unit
  if Quantity.is_basic_conversion_with_scalings?(self,new_unit)
    Quantity.new(@value,@unit).conversion_with_scalings! new_unit
  elsif self.unit.is_alternative_for? new_unit
    Quantity.new(@value,@unit).convert_to_equivalent_unit! new_unit
  elsif self.unit.is_compound_unit?
    Quantity.new(@value,@unit).convert_compound_unit_to_non_equivalent_unit! new_unit
  else
    nil # raise? or ...
  end      
end

#to_s(format = :symbol) ⇒ Object

Returns a string representation of the quantity, using the unit symbol



107
108
109
110
111
112
113
114
115
116
117
# File 'lib/quantify/quantity.rb', line 107

def to_s format=:symbol
  if format == :name
    if @value == 1 || @value == -1
      "#{@value} #{@unit.name}"
    else
      "#{@value} #{@unit.pluralized_name}"
    end
  else
    "#{@value} #{@unit.send format}"
  end
end

#to_siObject

Converts a quantity to the equivalent quantity using only SI units



153
154
155
156
157
158
159
# File 'lib/quantify/quantity.rb', line 153

def to_si
  if @unit.is_compound_unit?
    Quantity.new(@value,@unit).convert_compound_unit_to_si!
  else
    self.to(@unit.si_unit)
  end
end