quantify 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +151 -99
- data/lib/quantify/dimensions.rb +6 -6
- data/lib/quantify/exception.rb +14 -12
- data/lib/quantify/quantity.rb +17 -10
- data/lib/quantify/unit/base_unit.rb +6 -6
- data/lib/quantify/unit/compound_base_unit.rb +2 -2
- data/lib/quantify/unit/compound_unit.rb +6 -6
- data/lib/quantify/unit/prefix/base_prefix.rb +0 -2
- data/lib/quantify/unit/prefix/prefix.rb +1 -1
- data/lib/quantify/unit/unit.rb +4 -4
- data/spec/quantity_spec.rb +15 -0
- metadata +3 -3
data/README
CHANGED
|
@@ -1,115 +1,167 @@
|
|
|
1
|
-
A gem to support
|
|
1
|
+
A gem to support physical quantities and unit conversions
|
|
2
2
|
Licensed under the MIT license (See COPYING file for details)
|
|
3
3
|
Author: Andrew Berkeley (andrew.berkeley.is@googlemail.com)
|
|
4
4
|
Homepage: https://github.com/spatchcock/quantify
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
unit = Unit.km #=> #<Quantify::Unit::SI:0xb75c9718 ... >
|
|
9
|
-
unit.name #=> 'kilometre'
|
|
10
|
-
unit.symbol #=> 'kg'
|
|
11
|
-
unit.dimensions #=> #<Quantify::Dimensions:0xb75c4254 .. >
|
|
12
|
-
unit.measures #=> 'length'
|
|
13
|
-
unit.alternatives :name #=> ['metre', 'megametre', 'gigametre', 'terametre', 'angstrom',
|
|
14
|
-
# 'astronomical unit', 'baromil', 'chain', 'dram', 'ell', 'fathom',
|
|
15
|
-
# 'fermi', 'foot us survey', 'foot', 'furlong', 'hand', 'inch',
|
|
16
|
-
# 'nautical league', 'statute league', 'light year', 'line',
|
|
17
|
-
# 'link', 'yard']
|
|
18
|
-
other_unit = Unit.hour
|
|
19
|
-
other_unit.name #=> 'hour'
|
|
20
|
-
other_unit.symbol #=> 'h'
|
|
21
|
-
other_unit.measures #=> 'time'
|
|
22
|
-
other_unit.alternatives :symbol #=> [ 's', 'ks', 'Ms', 'Gs', 'Ts', 'd', 'min' ]
|
|
23
|
-
|
|
24
|
-
another_unit = unit / other_unit #=> #<Quantify::Unit::Compound:0xb74af323 ... >
|
|
25
|
-
another_unit.name #=> 'kilometer per hour'
|
|
26
|
-
another_unit.symbol #=> 'km h^-1'
|
|
27
|
-
another_unit.measures #=> 'velocity'
|
|
28
|
-
|
|
29
|
-
last_unit = Unit.m
|
|
30
|
-
last.unit.measures #=> 'length'
|
|
31
|
-
square = last_unit ** 2 #=> #<Quantify::Unit::Compound:0xb446f12f ... >
|
|
32
|
-
square.symbol #=> 'm^2'
|
|
33
|
-
square.measures #=> 'area'
|
|
34
|
-
|
|
35
|
-
Define quantity - method 1
|
|
36
|
-
|
|
37
|
-
quantity = Quantity.new(1234.5678, :lb) #=> #<Quantify::Quantity:0xjk39d570 ... >
|
|
38
|
-
quantity.value #=> 1234.5678
|
|
39
|
-
quantity.unit #=> #<Quantify::Unit::NonSI:0xb182124 ... >
|
|
40
|
-
quantity.unit.symbol #=> 'lb'
|
|
41
|
-
|
|
42
|
-
Define quantity - method 2
|
|
43
|
-
|
|
44
|
-
string = quantity.to_s #=> "1234.5678 lb"
|
|
45
|
-
quantity = Quantity.parse(string) #=> #<Quantify::Quantity:0xj982b4f9 ... >
|
|
46
|
-
quantity.to_s #=> "1234.5678 lb"
|
|
47
|
-
|
|
48
|
-
Define quantity - method 3
|
|
49
|
-
|
|
50
|
-
quantity = 1234.5678.lb #=> #<Quantify::Quantity:02387f7340 ... >
|
|
51
|
-
quantity.to_s #=> "1234.5678 lb"
|
|
52
|
-
|
|
53
|
-
Multiply by scalar
|
|
6
|
+
There are several ways to initialize a quantity object
|
|
54
7
|
|
|
55
|
-
|
|
56
|
-
|
|
8
|
+
mass = Quantity.new(100,:lb) => <Quantify::Quantity:0xb7332bbc ... >
|
|
9
|
+
mass = Quantity.new(100,'pound') => <Quantify::Quantity:0xb7332bbc ... >
|
|
10
|
+
mass = 100.lb => <Quantify::Quantity:0xb7332bbc ... >
|
|
11
|
+
mass = 100.pound => <Quantify::Quantity:0xb7332bbc ... >
|
|
12
|
+
mass = Quantity.parse "100 lb" => <Quantify::Quantity:0xb7332bbc ... >
|
|
13
|
+
mass = "100 lb".to_q => <Quantify::Quantity:0xb7332bbc ... >
|
|
57
14
|
|
|
58
|
-
|
|
15
|
+
Quantity object attributes
|
|
59
16
|
|
|
60
|
-
|
|
61
|
-
|
|
17
|
+
mass.value => 100.0
|
|
18
|
+
mass.unit => <Quantify::Unit::NonSI:0xb7332b08 ... >
|
|
19
|
+
mass.unit.name => "pound"
|
|
20
|
+
mass.unit.symbol => "lb"
|
|
62
21
|
|
|
63
|
-
|
|
64
|
-
|
|
22
|
+
# unique identifier, follows JScience
|
|
23
|
+
mass.unit.label => "lb"
|
|
24
|
+
mass.unit.pluralized_name => "pounds"
|
|
25
|
+
mass.to_s => "100 lb"
|
|
26
|
+
mass.to_s(:name) => "100 pounds"
|
|
65
27
|
|
|
66
|
-
|
|
28
|
+
# Describe the physical quantity represented by the quantity
|
|
29
|
+
mass.represents => "mass"
|
|
67
30
|
|
|
68
|
-
|
|
31
|
+
Convert a quantity to a different unit
|
|
69
32
|
|
|
70
|
-
|
|
33
|
+
energy = 100.kWh => <Quantify::Quantity:0xb7332bbc ... >
|
|
34
|
+
energy.to_s(:name) => "100 kilowatt hours"
|
|
71
35
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
kW.measures #=> 'power'
|
|
36
|
+
energy = quantity.to_megajoules => <Quantify::Quantity:0xb7332bbc ... >
|
|
37
|
+
energy.to_s => "360.0 MJ"
|
|
75
38
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
39
|
+
energy = quantity.to_MJ => <Quantify::Quantity:0xb7332bbc ... >
|
|
40
|
+
energy.to_s => "360.0 MJ"
|
|
41
|
+
|
|
42
|
+
energy = quantity.to(:MJ) => <Quantify::Quantity:0xb7332bbc ... >
|
|
43
|
+
energy.to_s => "360.0 MJ"
|
|
44
|
+
|
|
45
|
+
# Initialize a unit object and pass as conversion argument
|
|
46
|
+
unit = Unit.MJ => <Quantify::Unit::SI:0xb75c9718 ... >
|
|
47
|
+
energy = quantity.to(unit) => <Quantify::Quantity:0xb7332bbc ... >
|
|
48
|
+
energy.to_s => "360.0 MJ"
|
|
49
|
+
|
|
50
|
+
# Single line conversion of litres to barrels, returning only the value
|
|
51
|
+
5000.L.to_bbl.value => 31.4490528488754
|
|
52
|
+
|
|
53
|
+
Convert the units of a quantity with a compound unit
|
|
54
|
+
|
|
55
|
+
speed = 70.mi/1.h => <Quantify::Quantity:0xb7332bbc ... >
|
|
56
|
+
speed.to_s => "70.0 mi h^-1"
|
|
57
|
+
|
|
58
|
+
speed_in_kms = speed.to_km => <Quantify::Quantity:0xb7332bbc ... >
|
|
59
|
+
speed_in_kms.to_s => "112.65408 km h^-1"
|
|
60
|
+
|
|
61
|
+
speed_in_mins = speed_in_kms.to_min => <Quantify::Quantity:0xb7332bbc ... >
|
|
62
|
+
speed_in_mins.to_s => "1.877568 km min^-1"
|
|
63
|
+
|
|
64
|
+
Convert a quantity to the corresponding SI unit
|
|
65
|
+
|
|
66
|
+
energy = 100.kWh => <Quantify::Quantity:0xb7332bbc ... >
|
|
67
|
+
energy.to_s => "100 kWh"
|
|
68
|
+
si = quantity.to_si => <Quantify::Quantity:0x4j4j9sbc ... >
|
|
69
|
+
si.to_s => "360000000.0 J"
|
|
70
|
+
|
|
71
|
+
Operate on a quantity
|
|
72
|
+
|
|
73
|
+
mass = 10.kg * 3 => <Quantify::Quantity:0xb7332bbc ... >
|
|
74
|
+
mass.to_s => 30.0 kg
|
|
75
|
+
|
|
76
|
+
distance = 100.light_years / 20 => <Quantify::Quantity:0xb7332bbc ... >
|
|
77
|
+
distance.to_s => 5.0 ly
|
|
78
|
+
|
|
79
|
+
area = 10.m * 10.m => <Quantify::Quantity:0xb7332bbc ... >
|
|
80
|
+
area.to_s :name => 100.0 square metres
|
|
81
|
+
|
|
82
|
+
speed = 250.mi / 3.h => <Quantify::Quantity:0xb7332bbc ... >
|
|
83
|
+
speed.to_s(:name) => 83.3333333333333 miles per hour
|
|
84
|
+
|
|
85
|
+
speed = 70.mi/1.h => <Quantify::Quantity:0xb7332bbc ... >
|
|
86
|
+
time = 0.5.h => <Quantify::Quantity:3xf3472hjc ... >
|
|
87
|
+
distance = speed * time => <Quantify::Quantity:7d7f8g9d5g ... >
|
|
88
|
+
distance.to_s => 35.0 mi
|
|
89
|
+
|
|
90
|
+
Additional operations
|
|
91
|
+
The result of quantity operations is commonly a new quantity with a compound unit.
|
|
92
|
+
Unless the result is equivalent to one of the base SI units (m, kg, s, K, etc.) or
|
|
93
|
+
one of the following, square metre, cubic metre, joule, watt, newton or pascal, then
|
|
94
|
+
the compound unit represents appropriate combination of the units involved, albeit
|
|
95
|
+
with any like-units within the numerator and denominator grouped under a single
|
|
96
|
+
power/index.
|
|
97
|
+
|
|
98
|
+
Units are not automatically cancelled or rationalized (made consistent). This is
|
|
99
|
+
because it cannot be assumed that that is the desire of the user. For example, a
|
|
100
|
+
quantity with units <mass> per <mass> is technically dimensionless, but the user
|
|
101
|
+
might prefer to explicitly represent the units rather than reduce to a dimensionless
|
|
102
|
+
quantity. In addition, this quantity might be expressed in terms of grams per tonne,
|
|
103
|
+
and the user may not necessarily prefer a conversion into consistent mass units
|
|
104
|
+
(e.g. g/g or t/t). Therefore, the following methods are available...
|
|
105
|
+
|
|
106
|
+
# Where units representing the same physical quantity appear together, they can
|
|
107
|
+
# made consistent by simply converting to the unit which is desired
|
|
108
|
+
area = 12.yd * 36.ft => <Quantify::Quantity:0xb7332bbc ... >
|
|
109
|
+
area.to_s => "432.0 yd ft"
|
|
110
|
+
area.to_yd
|
|
111
|
+
area.to_s => "144.0 yd^2"
|
|
112
|
+
|
|
113
|
+
# Alternatively, all units within the numerator and denominator respectively
|
|
114
|
+
# can be standardized.
|
|
115
|
+
quantity = (12.ft*8.mi)/(1.s*8.min)
|
|
116
|
+
quantity.to_s => 12.0 ft mi s^-1 min^-1
|
|
117
|
+
quantity.rationalize_units!
|
|
118
|
+
quantity.to_s => 1056.0 ft^2 s^-2
|
|
119
|
+
|
|
120
|
+
# A quantity with arbitrary cancelable units can be cancelled manually
|
|
121
|
+
quantity = (12.m**6) / 2.m**2
|
|
122
|
+
quantity.to_s => "746496.0 m^6 m^-2"
|
|
123
|
+
quantity.cancel_base_units! :m
|
|
124
|
+
quantity.to_s => "746496.0 m^4"
|
|
125
|
+
|
|
126
|
+
Note: there are more comprehensive and flexible methods for manupulating compound
|
|
127
|
+
units available as part of of the class Unit::Compound. These can be used to
|
|
128
|
+
convert a conpound unit into the precise form required. If such an approach is
|
|
129
|
+
used, any quantity object can be converted to the new form by simply passing the
|
|
130
|
+
new unit object into the Quantity#to method.
|
|
131
|
+
|
|
132
|
+
Initialize a unit object
|
|
133
|
+
|
|
134
|
+
unit = Unit.for :km => <Quantify::Unit::SI:0xb75c9718 ... >
|
|
135
|
+
unit = Unit.km => <Quantify::Unit::SI:0xb75c9718 ... >
|
|
136
|
+
unit = Unit.kilometre => <Quantify::Unit::SI:0xb75c9718 ... >
|
|
137
|
+
|
|
138
|
+
unit.name => 'kilometre'
|
|
139
|
+
unit.symbol => 'kg'
|
|
140
|
+
unit.label => 'kg'
|
|
141
|
+
unit.dimensions => <Quantify::Dimensions:0xb75c4254 .. >
|
|
142
|
+
unit.measures => 'length'
|
|
143
|
+
unit.alternatives :name => ['metre','megametre','gigametre',
|
|
144
|
+
'terametre','angstrom','astronomical unit',
|
|
145
|
+
'baromil','chain','dram','ell','fathom',
|
|
146
|
+
'fermi','foot us survey','foot','furlong',
|
|
147
|
+
'hand','inch','nautical league',
|
|
148
|
+
'statute league','light year', 'line','link',
|
|
149
|
+
'yard']
|
|
79
150
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
kWh.alternatives :symbol #=> ['J', 'kJ', 'MJ', 'GJ', 'TJ', 'BTU', 'cal', 'CHU',
|
|
86
|
-
# 'dyn cm', 'eV', 'erg', 'Eh']
|
|
87
|
-
kWh.alternatives :name #=> ['joule', 'kilojoule', 'megajoule', 'gigajoule',
|
|
88
|
-
# 'terajoule', 'british thermal unit', 'calorie',
|
|
89
|
-
# 'celsius heat unit', 'dyne centimetre', 'electron volt',
|
|
90
|
-
# 'erg', 'hartree']
|
|
91
|
-
|
|
92
|
-
Create mass unit
|
|
93
|
-
|
|
94
|
-
kg = Unit.kg #=> #<Quantify::Unit::SI:0xb758b594 ... >
|
|
95
|
-
|
|
96
|
-
Create emission factor compound unit
|
|
97
|
-
|
|
98
|
-
kg_per_kWh = kg / kWh #=> #<Quantify::Unit::Compound:0xb746f093 ... >
|
|
99
|
-
kg_per_kWh.symbol #=> "kg_kW^-1_h^-1
|
|
100
|
-
kg_per_kWh.name #=> 'kilogram per kilowatt hour'
|
|
101
|
-
|
|
102
|
-
Create emission factor quantity
|
|
103
|
-
|
|
104
|
-
emission_factor = Quantity.new(0.54, kg_per_kWh) #=> #<Quantify::Quantity:0xb75cd570 ... >
|
|
105
|
-
emission_factor.to_s #=> "0.54 kg kW^-1 h^-1"
|
|
106
|
-
|
|
107
|
-
Create consumption quantity
|
|
108
|
-
|
|
109
|
-
consumption = Quantity.new(9885.5, kWh) #=> #<Quantify::Quantity:0xb7j4k3570 ... >
|
|
110
|
-
consumption.to_s #=> "9885.5 kWh"
|
|
151
|
+
other_unit = Unit.hour
|
|
152
|
+
other_unit.name => 'hour'
|
|
153
|
+
other_unit.symbol => 'h'
|
|
154
|
+
other_unit.measures => 'time'
|
|
155
|
+
other_unit.alternatives :symbol => [ 's', 'ks', 'Ms', 'Gs', 'Ts', 'd', 'min' ]
|
|
111
156
|
|
|
112
|
-
|
|
157
|
+
another_unit = unit / other_unit => <Quantify::Unit::Compound:0xb74af323 ... >
|
|
158
|
+
another_unit.name => 'kilometer per hour'
|
|
159
|
+
another_unit.symbol => 'km h^-1'
|
|
160
|
+
another_unit.measures => 'velocity'
|
|
161
|
+
another_unit.base_units.map(&:name) => ['kilogram','hour']
|
|
113
162
|
|
|
114
|
-
|
|
115
|
-
|
|
163
|
+
last_unit = Unit.m
|
|
164
|
+
last.unit.measures => 'length'
|
|
165
|
+
square = last_unit ** 2 => <Quantify::Unit::Compound:0xb446f12f ... >
|
|
166
|
+
square.symbol => 'm^2'
|
|
167
|
+
square.measures => 'area'
|
data/lib/quantify/dimensions.rb
CHANGED
|
@@ -76,7 +76,7 @@ module Quantify
|
|
|
76
76
|
if options[:physical_quantity]
|
|
77
77
|
@@dimensions << Dimensions.new(options)
|
|
78
78
|
else
|
|
79
|
-
raise InvalidDimensionError, "Cannot load dimensions without physical quantity description"
|
|
79
|
+
raise Exceptions::InvalidDimensionError, "Cannot load dimensions without physical quantity description"
|
|
80
80
|
end
|
|
81
81
|
end
|
|
82
82
|
|
|
@@ -122,10 +122,10 @@ module Quantify
|
|
|
122
122
|
end
|
|
123
123
|
return quantity.clone
|
|
124
124
|
else
|
|
125
|
-
raise InvalidArgumentError, "Physical quantity not known: #{name}"
|
|
125
|
+
raise Exceptions::InvalidArgumentError, "Physical quantity not known: #{name}"
|
|
126
126
|
end
|
|
127
127
|
else
|
|
128
|
-
raise InvalidArgumentError, "Argument must be a Symbol or String"
|
|
128
|
+
raise Exceptions::InvalidArgumentError, "Argument must be a Symbol or String"
|
|
129
129
|
end
|
|
130
130
|
end
|
|
131
131
|
|
|
@@ -202,9 +202,9 @@ module Quantify
|
|
|
202
202
|
if describe and not loaded?
|
|
203
203
|
@@dimensions << self
|
|
204
204
|
elsif describe
|
|
205
|
-
raise InvalidDimensionError, "A dimension instance with the same physical quantity already exists"
|
|
205
|
+
raise Exceptions::InvalidDimensionError, "A dimension instance with the same physical quantity already exists"
|
|
206
206
|
else
|
|
207
|
-
raise InvalidDimensionError, "Cannot load dimensions without physical quantity description"
|
|
207
|
+
raise Exceptions::InvalidDimensionError, "Cannot load dimensions without physical quantity description"
|
|
208
208
|
end
|
|
209
209
|
end
|
|
210
210
|
|
|
@@ -497,7 +497,7 @@ module Quantify
|
|
|
497
497
|
options.each_pair do |base_quantity,index|
|
|
498
498
|
base_quantity = base_quantity.to_s.downcase.to_sym
|
|
499
499
|
unless index.is_a? Integer and BASE_QUANTITIES.include? base_quantity
|
|
500
|
-
raise InvalidDimensionError, "An invalid base quantity was specified (#{base_quantity})"
|
|
500
|
+
raise Exceptions::InvalidDimensionError, "An invalid base quantity was specified (#{base_quantity})"
|
|
501
501
|
end
|
|
502
502
|
variable = "@#{base_quantity}"
|
|
503
503
|
if self.instance_variable_defined?(variable)
|
data/lib/quantify/exception.rb
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
module Quantify
|
|
2
|
+
module Exceptions
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
class QuantityParseError < Exception
|
|
5
|
+
end
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
class InvalidObjectError < Exception
|
|
8
|
+
end
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
class InvalidUnitError < Exception
|
|
11
|
+
end
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
class InvalidDimensionError < Exception
|
|
14
|
+
end
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
class InvalidPhysicalQuantityError < Exception
|
|
17
|
+
end
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
class InvalidArgumentError < Exception
|
|
20
|
+
end
|
|
21
|
+
|
|
19
22
|
end
|
|
20
|
-
|
|
21
23
|
end
|
data/lib/quantify/quantity.rb
CHANGED
|
@@ -47,10 +47,10 @@ module Quantify
|
|
|
47
47
|
if quantity = /\A([\d\s.,]+)(\D+.*)\z/.match(string)
|
|
48
48
|
Quantity.new($1.strip, $2)
|
|
49
49
|
else
|
|
50
|
-
raise Quantify::QuantityParseError, "Cannot parse string into value and unit"
|
|
50
|
+
raise Quantify::Exceptions::QuantityParseError, "Cannot parse string into value and unit"
|
|
51
51
|
end
|
|
52
|
-
rescue Quantify::InvalidArgumentError
|
|
53
|
-
raise Quantify::QuantityParseError, "Cannot parse string into value and unit"
|
|
52
|
+
rescue Quantify::Exceptions::InvalidArgumentError
|
|
53
|
+
raise Quantify::Exceptions::QuantityParseError, "Cannot parse string into value and unit"
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def self.configure &block
|
|
@@ -195,10 +195,10 @@ module Quantify
|
|
|
195
195
|
@value = value.send operator, other.value
|
|
196
196
|
return self
|
|
197
197
|
else
|
|
198
|
-
raise Quantify::InvalidObjectError "Cannot add or subtract Quantities with different dimensions"
|
|
198
|
+
raise Quantify::Exceptions::InvalidObjectError "Cannot add or subtract Quantities with different dimensions"
|
|
199
199
|
end
|
|
200
200
|
else
|
|
201
|
-
raise Quantify::InvalidObjectError "Cannot add or subtract non-Quantity objects"
|
|
201
|
+
raise Quantify::Exceptions::InvalidObjectError "Cannot add or subtract non-Quantity objects"
|
|
202
202
|
end
|
|
203
203
|
end
|
|
204
204
|
|
|
@@ -211,12 +211,12 @@ module Quantify
|
|
|
211
211
|
@value = value.send(operator,other.value)
|
|
212
212
|
return self
|
|
213
213
|
else
|
|
214
|
-
raise Quantify::InvalidArgumentError "Cannot multiply or divide a Quantity by a non-Quantity or non-Numeric object"
|
|
214
|
+
raise Quantify::Exceptions::InvalidArgumentError "Cannot multiply or divide a Quantity by a non-Quantity or non-Numeric object"
|
|
215
215
|
end
|
|
216
216
|
end
|
|
217
217
|
|
|
218
218
|
def pow!(power)
|
|
219
|
-
raise InvalidArgumentError, "Argument must be an integer" unless power.is_a? Integer
|
|
219
|
+
raise Exceptions::InvalidArgumentError, "Argument must be an integer" unless power.is_a? Integer
|
|
220
220
|
@value = value ** power
|
|
221
221
|
@unit = unit ** power
|
|
222
222
|
return self
|
|
@@ -267,7 +267,14 @@ module Quantify
|
|
|
267
267
|
|
|
268
268
|
def rationalize_units
|
|
269
269
|
return self unless unit.is_a? Unit::Compound
|
|
270
|
-
self.to unit.rationalize_base_units
|
|
270
|
+
self.to unit.clone.rationalize_base_units!
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def rationalize_units!
|
|
274
|
+
rationalized_quantity = self.rationalize_units
|
|
275
|
+
@value = rationalized_quantity.value
|
|
276
|
+
@unit = rationalized_quantity.unit
|
|
277
|
+
return self
|
|
271
278
|
end
|
|
272
279
|
|
|
273
280
|
def cancel_base_units!(*units)
|
|
@@ -303,7 +310,7 @@ module Quantify
|
|
|
303
310
|
if object.kind_of? Numeric
|
|
304
311
|
return Quantity.new(object, Unit.unity), self
|
|
305
312
|
else
|
|
306
|
-
raise InvalidArgumentError, "Cannot coerce #{self.class} into #{object.class}"
|
|
313
|
+
raise Exceptions::InvalidArgumentError, "Cannot coerce #{self.class} into #{object.class}"
|
|
307
314
|
end
|
|
308
315
|
end
|
|
309
316
|
|
|
@@ -317,7 +324,7 @@ module Quantify
|
|
|
317
324
|
if method.to_s =~ /(to_)(.*)/
|
|
318
325
|
to($2)
|
|
319
326
|
else
|
|
320
|
-
|
|
327
|
+
super
|
|
321
328
|
end
|
|
322
329
|
end
|
|
323
330
|
|
|
@@ -110,7 +110,7 @@ module Quantify
|
|
|
110
110
|
elsif options[:dimensions].is_a? String or options[:dimensions].is_a? Symbol
|
|
111
111
|
@dimensions = Dimensions.for options[:dimensions]
|
|
112
112
|
else
|
|
113
|
-
raise InvalidArgumentError, "Unknown physical_quantity specified"
|
|
113
|
+
raise Exceptions::InvalidArgumentError, "Unknown physical_quantity specified"
|
|
114
114
|
end
|
|
115
115
|
@factor = options[:factor].nil? ? 1.0 : options[:factor].to_f
|
|
116
116
|
@symbol = options[:symbol].nil? ? nil : options[:symbol].standardize
|
|
@@ -145,7 +145,7 @@ module Quantify
|
|
|
145
145
|
#
|
|
146
146
|
def load
|
|
147
147
|
yield self if block_given?
|
|
148
|
-
raise InvalidArgumentError, "A unit with the same label: #{self.name}) already exists" if loaded?
|
|
148
|
+
raise Exceptions::InvalidArgumentError, "A unit with the same label: #{self.name}) already exists" if loaded?
|
|
149
149
|
Quantify::Unit.units << self if valid?
|
|
150
150
|
end
|
|
151
151
|
|
|
@@ -327,7 +327,7 @@ module Quantify
|
|
|
327
327
|
|
|
328
328
|
def valid?
|
|
329
329
|
return true if valid_descriptors? and valid_dimensions?
|
|
330
|
-
raise InvalidArgumentError, "Unit definition must include a name, a symbol, a label and physical quantity"
|
|
330
|
+
raise Exceptions::InvalidArgumentError, "Unit definition must include a name, a symbol, a label and physical quantity"
|
|
331
331
|
end
|
|
332
332
|
|
|
333
333
|
def valid_descriptors?
|
|
@@ -428,7 +428,7 @@ module Quantify
|
|
|
428
428
|
#
|
|
429
429
|
def with_prefix(name_or_symbol)
|
|
430
430
|
if self.name =~ /\A(#{valid_prefixes(:name).join("|")})/
|
|
431
|
-
raise InvalidArgumentError, "Cannot add prefix where one already exists: #{self.name}"
|
|
431
|
+
raise Exceptions::InvalidArgumentError, "Cannot add prefix where one already exists: #{self.name}"
|
|
432
432
|
end
|
|
433
433
|
|
|
434
434
|
prefix = Unit::Prefix.for(name_or_symbol,valid_prefixes)
|
|
@@ -442,7 +442,7 @@ module Quantify
|
|
|
442
442
|
new_unit_options[:physical_quantity] = self.dimensions
|
|
443
443
|
self.class.new(new_unit_options)
|
|
444
444
|
else
|
|
445
|
-
raise InvalidArgumentError, "Prefix unit is not known: #{prefix}"
|
|
445
|
+
raise Exceptions::InvalidArgumentError, "Prefix unit is not known: #{prefix}"
|
|
446
446
|
end
|
|
447
447
|
end
|
|
448
448
|
|
|
@@ -472,7 +472,7 @@ module Quantify
|
|
|
472
472
|
if object.kind_of? Numeric and object == 1
|
|
473
473
|
return Unit.unity, self
|
|
474
474
|
else
|
|
475
|
-
raise InvalidArgumentError, "Cannot coerce #{self.class} into #{object.class}"
|
|
475
|
+
raise Exceptions::InvalidArgumentError, "Cannot coerce #{self.class} into #{object.class}"
|
|
476
476
|
end
|
|
477
477
|
end
|
|
478
478
|
|
|
@@ -14,8 +14,8 @@ module Quantify
|
|
|
14
14
|
attr_accessor :unit, :index
|
|
15
15
|
|
|
16
16
|
def initialize(unit,index=1)
|
|
17
|
-
@unit = Unit.match(unit) || raise(InvalidUnitError, "Base unit not known: #{unit}")
|
|
18
|
-
raise InvalidUnitError, "Base unit cannot be compound unit" if @unit.is_a? Compound
|
|
17
|
+
@unit = Unit.match(unit) || raise(Exceptions::InvalidUnitError, "Base unit not known: #{unit}")
|
|
18
|
+
raise Exceptions::InvalidUnitError, "Base unit cannot be compound unit" if @unit.is_a? Compound
|
|
19
19
|
@index = index
|
|
20
20
|
end
|
|
21
21
|
|
|
@@ -32,7 +32,7 @@ module Quantify
|
|
|
32
32
|
# base units or just a subset - the numerator or denominator units.
|
|
33
33
|
#
|
|
34
34
|
def self.consolidate_base_units(base_units)
|
|
35
|
-
raise InvalidArgumentError, "Must provide an array of base units" unless base_units.is_a? Array
|
|
35
|
+
raise Exceptions::InvalidArgumentError, "Must provide an array of base units" unless base_units.is_a? Array
|
|
36
36
|
|
|
37
37
|
new_base_units = []
|
|
38
38
|
|
|
@@ -97,7 +97,7 @@ module Quantify
|
|
|
97
97
|
not unit.first.is_a? Compound and unit.size == 2
|
|
98
98
|
@base_units << CompoundBaseUnit.new(unit.first,unit.last)
|
|
99
99
|
else
|
|
100
|
-
raise InvalidArgumentError, "#{unit} does not represent a valid base unit"
|
|
100
|
+
raise Exceptions::InvalidArgumentError, "#{unit} does not represent a valid base unit"
|
|
101
101
|
end
|
|
102
102
|
end
|
|
103
103
|
@acts_as_alternative_unit = true
|
|
@@ -158,7 +158,7 @@ module Quantify
|
|
|
158
158
|
#
|
|
159
159
|
def cancel_base_units!(*units)
|
|
160
160
|
units.each do |unit|
|
|
161
|
-
raise InvalidArgumentError, "Cannot cancel by a compound unit" if unit.is_a? Unit::Compound
|
|
161
|
+
raise Exceptions::InvalidArgumentError, "Cannot cancel by a compound unit" if unit.is_a? Unit::Compound
|
|
162
162
|
unit = Unit.for unit unless unit.is_a? Unit::Base
|
|
163
163
|
|
|
164
164
|
numerator_unit = numerator_units.find { |base| unit == base.unit }
|
|
@@ -175,10 +175,10 @@ module Quantify
|
|
|
175
175
|
|
|
176
176
|
def rationalize_base_units!(scope=:partial,*units)
|
|
177
177
|
if scope == :full
|
|
178
|
-
Compound.rationalize_base_units(@base_units
|
|
178
|
+
Compound.rationalize_base_units(@base_units,*units)
|
|
179
179
|
else
|
|
180
|
-
Compound.rationalize_base_units(numerator_units
|
|
181
|
-
Compound.rationalize_base_units(denominator_units
|
|
180
|
+
Compound.rationalize_base_units(numerator_units,*units)
|
|
181
|
+
Compound.rationalize_base_units(denominator_units,*units)
|
|
182
182
|
end
|
|
183
183
|
consolidate_numerator_and_denominator_units!
|
|
184
184
|
end
|
data/lib/quantify/unit/unit.rb
CHANGED
|
@@ -60,7 +60,7 @@ module Quantify
|
|
|
60
60
|
unit = Unit.for unit
|
|
61
61
|
other_unit = Unit.for other_unit
|
|
62
62
|
unless unit.is_alternative_for? other_unit
|
|
63
|
-
raise InvalidUnitError, "Units do not represent the same physical quantity"
|
|
63
|
+
raise Exceptions::InvalidUnitError, "Units do not represent the same physical quantity"
|
|
64
64
|
end
|
|
65
65
|
new_unit = (unit / other_unit)
|
|
66
66
|
value = 1/new_unit.factor
|
|
@@ -94,7 +94,7 @@ module Quantify
|
|
|
94
94
|
( name_symbol_label_or_object.is_a?(String) and name_symbol_label_or_object.empty? )
|
|
95
95
|
name_symbol_or_label = name_symbol_label_or_object
|
|
96
96
|
unless name_symbol_or_label.is_a? String or name_symbol_or_label.is_a? Symbol
|
|
97
|
-
raise InvalidArgumentError, "Argument must be a Symbol or String"
|
|
97
|
+
raise Exceptions::InvalidArgumentError, "Argument must be a Symbol or String"
|
|
98
98
|
end
|
|
99
99
|
if unit = Unit.match(name_symbol_or_label)
|
|
100
100
|
return unit
|
|
@@ -102,7 +102,7 @@ module Quantify
|
|
|
102
102
|
if unit = Unit.parse(name_symbol_or_label)
|
|
103
103
|
return unit
|
|
104
104
|
end
|
|
105
|
-
rescue InvalidUnitError
|
|
105
|
+
rescue Exceptions::InvalidUnitError
|
|
106
106
|
return nil
|
|
107
107
|
end
|
|
108
108
|
|
|
@@ -111,7 +111,7 @@ module Quantify
|
|
|
111
111
|
def self.parse(string)
|
|
112
112
|
string = string.standardize
|
|
113
113
|
if string.scan(/(\/|per)/).size > 1
|
|
114
|
-
raise InvalidArgumentError, "Malformed unit: multiple uses of '/' or 'per'"
|
|
114
|
+
raise Exceptions::InvalidArgumentError, "Malformed unit: multiple uses of '/' or 'per'"
|
|
115
115
|
end
|
|
116
116
|
|
|
117
117
|
units = []
|
data/spec/quantity_spec.rb
CHANGED
|
@@ -246,5 +246,20 @@ describe Quantity do
|
|
|
246
246
|
quantity.unit.base_units.size.should == 1
|
|
247
247
|
quantity.to_s.should == "40.720412743579 inHg"
|
|
248
248
|
end
|
|
249
|
+
|
|
250
|
+
it "should rationalize units and return new quantity" do
|
|
251
|
+
quantity = 12.yards*36.feet
|
|
252
|
+
quantity.to_s.should eql "432.0 yd ft"
|
|
253
|
+
new_quantity=quantity.rationalize_units
|
|
254
|
+
quantity.to_s.should eql "432.0 yd ft"
|
|
255
|
+
new_quantity.to_s.should eql "144.0 yd^2"
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
it "should rationalize units and modify value in place" do
|
|
259
|
+
quantity = 12.yards*36.feet
|
|
260
|
+
quantity.to_s.should eql "432.0 yd ft"
|
|
261
|
+
quantity.rationalize_units!
|
|
262
|
+
quantity.to_s.should eql "144.0 yd^2"
|
|
263
|
+
end
|
|
249
264
|
end
|
|
250
265
|
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: quantify
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
hash:
|
|
4
|
+
hash: 17
|
|
5
5
|
prerelease:
|
|
6
6
|
segments:
|
|
7
7
|
- 1
|
|
8
8
|
- 0
|
|
9
|
-
-
|
|
10
|
-
version: 1.0.
|
|
9
|
+
- 3
|
|
10
|
+
version: 1.0.3
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- Andrew Berkeley
|