Class: Quantity

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/quantity.rb,
lib/quantity/unit.rb,
lib/quantity/version.rb,
lib/quantity/dimension.rb,
lib/quantity/systems/si.rb,
lib/quantity/dimension/base.rb,
lib/quantity/systems/enumerable.rb,
lib/quantity/systems/information.rb

Overview

a few countable quantities

Instance Attribute Summary

Instance Method Summary

Constructor Details

- (Quantity) initialize(value, unit, options) - (Quantity) initialize(options)

Initialize a new, immutable quantity

Overloads:

  • - (Quantity) initialize(value, unit, options)

    Parameters:

  • - (Quantity) initialize(options)

    Only one of value or reference value can be used, if both are given, reference value will be used.

    Parameters:

    • (Hash{Symbol => Object}) options

    Options Hash (options):

    • (Numeric) :value N/A —Visible value
    • (Numeric) :reference_value N/A —Reference value
    • (Symbol Unit) :unit N/A —Units


69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/quantity.rb', line 69

def initialize(value, unit = nil )
  case value
    when Hash
      @unit = Unit.for(value[:unit])
      @reference_value = value[:reference_value] || (value[:value] * @unit.value)
      @value = @unit.value_for(@reference_value) #dimension.reference.convert_proc(@unit).call(@reference_value)
      #@value = @unit.convert_proc(@unit).call(@reference_value)
    when Numeric
      @unit = Unit.for(unit)
      if @unit.nil?
        @unit = Unit.from_string_form(unit)
      end
      @value = value
      @reference_value = value * @unit.value 
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

- (Object) method_missing(method, *args, &block)

this creates the conversion methods of .to* and .in*



351
352
353
354
355
356
357
358
359
360
361
# File 'lib/quantity.rb', line 351

def method_missing(method, *args, &block)
  if method.to_s =~ /(to_|in_)(.*)/
    if (Unit.is_unit?($2.to_sym))
      convert($2.to_sym)
    else
      raise ArgumentError, "Unknown target unit type: #{$2}"
    end
  else 
    raise NoMethodError, "Undefined method `#{method}` for #{self}:#{self.class}"
  end
end

Instance Attribute Details

- (Object) reference_value (readonly)

This quantity in terms of the reference value, declared by fiat for everything measurable



51
52
53
# File 'lib/quantity.rb', line 51

def reference_value
  @reference_value
end

- (Object) unit (readonly)

Unit of measurement



48
49
50
# File 'lib/quantity.rb', line 48

def unit
  @unit
end

- (Object) value (readonly)

User-visible value, i.e. 2.meters.value == 2



45
46
47
# File 'lib/quantity.rb', line 45

def value
  @value
end

Instance Method Details

- (Quantity) %(other) Also known as: modulo

Mod

Returns:



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

def %(other)
  if (other.is_a?(Numeric))
    Quantity.new(@value % other, @unit)
  elsif(other.is_a?(Quantity) && self.measures == other.measures)
    Quantity.new({:unit => @unit, :reference_value => @reference_value % other.reference_value})
  else
    raise ArgumentError, "Cannot modulo #{other} with #{self}"
  end
end

- (Quantity) *(other)

Multiplication.

Parameters:

Returns:



181
182
183
184
185
186
187
188
189
# File 'lib/quantity.rb', line 181

def *(other)
  if (other.is_a?(Numeric))
    Quantity.new(@value * other, @unit)
  elsif(other.is_a?(Quantity))
    Quantity.new({:unit => other.unit * @unit, :reference_value => @reference_value * other.reference_value})
  else
    raise ArgumentError, "Cannot multiply #{other} with #{self}"
  end
end

- (Quantity) **(power)

Exponentiation. Quantities cannot be raised to negative or fractional powers, only positive Fixnum.

Parameters:

Returns:



216
217
218
219
220
221
222
223
224
225
# File 'lib/quantity.rb', line 216

def **(power)
  unless power.is_a?(Fixnum) && power > 0
    raise ArgumentError, "Quantities can only be raised to fixed powers (given #{power})"
  end
  if power == 1
    self
  else
    self * self**(power - 1)
  end
end

- (Quantity) +(other)

Addition. Add two quantities of the same type. Do not need to have the same units.

Parameters:

Returns:



133
134
135
136
137
138
139
140
141
# File 'lib/quantity.rb', line 133

def +(other)
  if (other.is_a?(Numeric))
    Quantity.new(@value + other, @unit)
  elsif(other.is_a?(Quantity) && @unit.dimension == other.unit.dimension)
    Quantity.new({:unit => @unit,:reference_value => @reference_value + other.reference_value})
  else
    raise ArgumentError,"Cannot add #{self} to #{other}"
  end
end

- (Quantity) +@

Unary + (self)

Returns:



266
267
268
# File 'lib/quantity.rb', line 266

def +@
  self
end

- (Quantity) -(other)

Subtraction. Subtract a quantity from another of the same type. They do not need to share units.

Parameters:

Returns:



147
148
149
150
151
152
153
154
155
# File 'lib/quantity.rb', line 147

def -(other)
  if (other.is_a?(Numeric))
    Quantity.new(@value - other, @unit)
  elsif(other.is_a?(Quantity) && @unit.dimension == other.unit.dimension)
    Quantity.new({:unit => @unit,:reference_value => @reference_value - other.reference_value})
  else
    raise ArgumentError, "Cannot subtract #{other} from #{self}"
  end
end

- (Quantity) /(other)

Division

Parameters:

Returns:



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/quantity.rb', line 194

def /(other)
  if (other.is_a?(Numeric))
    Quantity.new(@value / other, @unit)
  elsif(other.is_a?(Quantity))
    ref = nil
    if defined?(Rational) && (@value.is_a?(Fixnum)) && (other.is_a?(Fixnum))
      ref = Rational(@reference_value,other.reference_value)
    elsif defined?(Rational) && (@value.is_a?(Rational)) && (other.is_a?(Rational))
      ref = @reference_value / other.reference_value
    else
      ref = @reference_value / other.reference_value.to_f
    end
    Quantity.new({:unit => @unit / other.unit, :reference_value => ref})
  else
    raise ArgumentError, "Cannot multiply #{other} with #{self}"
  end
end

- (-1 0 1) <=>(other)

Comparison. Compare this to another quantity or numeric. Compared to a numeric, this will assume a numeric of the same unit as self.

Parameters:

Returns:

  • (-1 0 1)


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

def <=>(other)
  if (other.is_a?(Numeric))
    @value <=> other
  elsif(other.is_a?(Quantity) && measures == other.measures)
    @reference_value <=> other.reference_value
  else
    nil
  end
end

- (Quantity) abs

Abs implementation

Returns:



107
108
109
110
111
112
113
# File 'lib/quantity.rb', line 107

def abs
  if @reference_value < 0
    -self
  else
    self
  end
end

- (Quantity) ceil

Smallest integer quantity greater than or equal to this

Returns:



302
303
304
# File 'lib/quantity.rb', line 302

def ceil
  Quantity.new(@value.ceil, @unit)
end

- (Quantity, Quantity) coerce(other)

Ruby coercion. Allows things like 2 + 5.meters

Returns:



117
118
119
120
121
122
123
124
125
126
127
# File 'lib/quantity.rb', line 117

def coerce(other)
  if other.class == @value.class
    [Quantity.new(other, @unit),self]
  elsif defined?(Rational) && (@value.is_a?(Fixnum)) && (other.is_a?(Fixnum))
    [Quantity.new(Rational(other), @unit), self] 
  elsif defined?(Rational) && (other.is_a?(Rational))
    [Quantity.new(other, @unit), self] 
  else
    [Quantity.new(other.to_f, @unit),Quantity.new(@value.to_f, @unit)]
  end
end

- (Object) convert(to)

Convert to another unit of measurement. For most uses, Quantity#to_ is what you want, but this can be handy for variable units.

Parameters:



330
331
332
# File 'lib/quantity.rb', line 330

def convert(to)
  Quantity.new({:unit => @unit.convert(to), :reference_value => @reference_value})
end

- (Quantity) cubed

Cube the units of this quantity

Examples:

    4.meters.cubed == Quantity.new(4.'m^3')

Returns:



239
240
241
# File 'lib/quantity.rb', line 239

def cubed
  Quantity.new(@value, @unit * @unit * @unit)
end

- (Quantity, Quantity) divmod(other)

Divmod

Returns:



308
309
310
311
312
313
314
315
316
317
318
# File 'lib/quantity.rb', line 308

def divmod(other)
  if (other.is_a?(Numeric))
    (q, r) = @value.divmod(other)
    [Quantity.new(q,@unit),Quantity.new(r,@unit)]
  elsif (other.is_a?(Quantity) && measures == other.measures)
    (q, r) = @value.divmod(other.value)
    [Quantity.new(q,@unit),Quantity.new(r,@unit)]
  else
    raise ArgumentError, "Cannot divmod #{other} with #{self}"
  end
end

- (Boolean) eql?(other)

Type-aware equality

Parameters:

  • (Any)

Returns:

  • (Boolean)


174
175
176
# File 'lib/quantity.rb', line 174

def eql?(other)
  other.is_a?(Quantity) && other.units == units && self == other
end

- (Quantity) floor

Largest integer quantity less than or equal to this

Returns:



296
297
298
# File 'lib/quantity.rb', line 296

def floor
  Quantity.new(@value.floor, @unit)
end

- (String) inspect

Developer-friendly string representation

Returns:

  • (String)


345
346
347
# File 'lib/quantity.rb', line 345

def inspect
  to_s
end

- (Symbol String) measures

What this measures

Returns:

  • (Symbol String) — What this measures. Derived types will be a string


95
96
97
# File 'lib/quantity.rb', line 95

def measures
  @unit.dimension
end

- (Quantity) round

Round this value to the nearest integer

Returns:



284
285
286
# File 'lib/quantity.rb', line 284

def round
  Quantity.new(@value.round, @unit)
end

- (Quantity) squared

Square the units of this quantity

Examples:

    4.meters.squared == Quantity.new(4.'m^2')

Returns:



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

def squared
  Quantity.new(@value, @unit * @unit)
end

- (Float) to_f

Float representation

Returns:

  • (Float)


278
279
280
# File 'lib/quantity.rb', line 278

def to_f
  @value.to_f
end

- (Fixnum) to_i

Integer representation

Returns:

  • (Fixnum)


272
273
274
# File 'lib/quantity.rb', line 272

def to_i
  @value.to_i
end

- (String) to_s

String version of this quantity

Parameters:

  • (String) format — Format for sprintf, will be given

Returns:

  • (String)


89
90
91
# File 'lib/quantity.rb', line 89

def to_s
  @unit.s_for(value)
end

- (Quantity) truncate

Truncate this value to an integer

Returns:



290
291
292
# File 'lib/quantity.rb', line 290

def truncate
  Quantity.new(@value.truncate, @unit)
end

- (Symbol String) units

Units of measurement

Returns:

  • (Symbol String) — Units of measurement. Derived types will be a string


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

def units
  @unit.name
end

- (Boolean) zero?

Returns true if self has a zero value

Returns:

  • (Boolean)


322
323
324
# File 'lib/quantity.rb', line 322

def zero?
  @value.zero?
end