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



123
124
125
126
# File 'lib/quantify/quantity.rb', line 123

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"


394
395
396
397
398
399
400
# File 'lib/quantify/quantity.rb', line 394

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.



117
118
119
# File 'lib/quantify/quantity.rb', line 117

def unit
  @unit
end

#valueObject

Returns the value of attribute value.



117
118
119
# File 'lib/quantify/quantity.rb', line 117

def value
  @value
end

Class Method Details

.auto_consolidate_units=(true_or_false) ⇒ Object



97
98
99
# File 'lib/quantify/quantity.rb', line 97

def self.auto_consolidate_units=(true_or_false)
  @auto_consolidate_units = true_or_false
end

.auto_consolidate_units?Boolean

Returns:

  • (Boolean)


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

def self.auto_consolidate_units?
  @auto_consolidate_units.nil? ? false : @auto_consolidate_units
end

.configure(&block) ⇒ Object



93
94
95
# File 'lib/quantify/quantity.rb', line 93

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

.parse(string, options = {}) ⇒ 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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/quantify/quantity.rb', line 47

def self.parse(string,options={})
  
  quantities   = []
  remainder    = []
  words        = string.words

  until words.empty? do
    word = words.shift
    if word.starts_with_number?
      if (Unit::QUANTITY_REGEX).match(word)
        word, other = $1, $2
        words.unshift(other)
      end
      quantities << [word]
    else
      if quantities.empty?
        remainder << word
      else
        quantities.last << word
      end
    end
  end      

  remainders = []
  remainders << remainder.join(" ")

  quantities.map! do |words|

    value = words.shift
    string = words.join(" ")

    # Parse string for unit references
    unit, remainder = Unit.parse(string, :iterative => true, :remainder => true) 
    unit, remainder = Unit.dimensionless, string if unit.nil?
    remainders << remainder

    # Instantiate quantity using value and unit
    Quantity.new(value,unit)
      
  end.compact
  return [quantities, remainders] if options[:remainder] == true
  return quantities
rescue Quantify::Exceptions::InvalidArgumentError
  raise Quantify::Exceptions::QuantityParseError, "Cannot parse string into value and unit"
end

Instance Method Details

#<=>(other) ⇒ Object



281
282
283
284
285
286
# File 'lib/quantify/quantity.rb', line 281

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



288
289
290
291
# File 'lib/quantify/quantity.rb', line 288

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

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



220
221
222
# File 'lib/quantify/quantity.rb', line 220

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

#add!(other) ⇒ Object



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

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

#cancel_base_units!(*units) ⇒ Object



258
259
260
261
# File 'lib/quantify/quantity.rb', line 258

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: /



236
237
238
# File 'lib/quantify/quantity.rb', line 236

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

#divide!(other) ⇒ Object



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

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

#inspectObject



155
156
157
# File 'lib/quantify/quantity.rb', line 155

def inspect
  to_s
end

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



230
231
232
# File 'lib/quantify/quantity.rb', line 230

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

#multiply!(other) ⇒ Object



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

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

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



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

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

#pow!(power) ⇒ Object



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

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



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

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

#rationalize_units!Object



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

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


138
139
140
# File 'lib/quantify/quantity.rb', line 138

def represents
  @unit.measures
end

#round(decimal_places = 0) ⇒ Object

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



276
277
278
279
# File 'lib/quantify/quantity.rb', line 276

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



267
268
269
270
271
# File 'lib/quantify/quantity.rb', line 267

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: -



225
226
227
# File 'lib/quantify/quantity.rb', line 225

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

#subtract!(other) ⇒ Object



208
209
210
# File 'lib/quantify/quantity.rb', line 208

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.



175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/quantify/quantity.rb', line 175

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



143
144
145
146
147
148
149
150
151
152
153
# File 'lib/quantify/quantity.rb', line 143

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



189
190
191
192
193
194
195
# File 'lib/quantify/quantity.rb', line 189

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