numeric_with_unit 0.0.4 → 0.1.0
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.
- checksums.yaml +4 -4
- data/LICENSE +21 -0
- data/README.md +162 -0
- data/lib/numeric_with_unit/core_ext.rb +32 -0
- data/lib/numeric_with_unit/unit.rb +26 -9
- data/lib/numeric_with_unit/unit_definition/base.rb +11 -11
- data/lib/numeric_with_unit/unit_definition/cgs.rb +0 -0
- data/lib/numeric_with_unit/unit_definition/common.rb +27 -25
- data/lib/numeric_with_unit/unit_definition/deprecated.rb +44 -0
- data/lib/numeric_with_unit/unit_definition/imperial.rb +0 -0
- data/lib/numeric_with_unit/unit_definition/natural.rb +0 -0
- data/lib/numeric_with_unit/util.rb +1 -1
- data/lib/numeric_with_unit/util2.rb +14 -12
- data/lib/numeric_with_unit.rb +75 -66
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 757d20434e2556a232c44455278317111626a717
|
4
|
+
data.tar.gz: 29a86bf1e906c35b49104ede8013e07ff392aaba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ef1f289645e9fea40ec7674bc64c514355bef6705502214339b162d68f64153c230c768d1198315c6b0ff409d79835d8bb4751b4a82ff611cac119228eeee90
|
7
|
+
data.tar.gz: 70ea80a9ff0b464a69a1e64367e9365e80d532b9e4ab2a81b2cbcc5e6104101abf2da4195278bc75db106fea890cf7ad0b372dca71606376af1bd079c270901d
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 diaphragm
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
ruby-numeric-with-unit
|
2
|
+
======================
|
3
|
+
単位付き数値を提供します。したいです。
|
4
|
+
|
5
|
+
インストール
|
6
|
+
======================
|
7
|
+
|
8
|
+
$ gem install numeric_with_unit
|
9
|
+
|
10
|
+
使い方
|
11
|
+
======================
|
12
|
+
|
13
|
+
require 'numeric_with_unit'
|
14
|
+
|
15
|
+
#例1
|
16
|
+
length = NumericWithUnit.new(10, 'm') #10[m]を表すオブジェクトです。
|
17
|
+
puts length #=> 10 m
|
18
|
+
puts length['cm'] #=> 1000 cm
|
19
|
+
|
20
|
+
time = 10.to_nwu('s') #Fixnum#to_nwuが追加されるので、これを用いてもOKです。10[s]を表すオブジェクトです。
|
21
|
+
puts time #=> 10 s
|
22
|
+
puts time['min'] #=> 0.16666666666666666 min
|
23
|
+
|
24
|
+
speed = length / time
|
25
|
+
puts speed #=> 1 m/(s)
|
26
|
+
puts speed['km/hr'] #=> 3.6 km/(hr)
|
27
|
+
|
28
|
+
require 'numeric_with_unit/util' #自然な表記で記述できるようにします。
|
29
|
+
puts (10['m'] / 10['s'] )['km/hr'] #=> 3.6 km/(hr)
|
30
|
+
|
31
|
+
#例2
|
32
|
+
puts (50['L/min'] + 3['m3/hr'] ) * 30['min'] #=> 3000 L
|
33
|
+
|
34
|
+
|
35
|
+
* `require 'numeric_with_unit/util'`すると`Numeric#[]`と`Fixnum#[]`と`Bignum#[]`がオーバーライドされます。注意。
|
36
|
+
|
37
|
+
|
38
|
+
class NumericWith::Unit
|
39
|
+
======================
|
40
|
+
"単位"を表すクラスです。
|
41
|
+
|
42
|
+
Unit.new
|
43
|
+
----------------------
|
44
|
+
|
45
|
+
km = NumericWith::Unit.new do |conf|
|
46
|
+
conf.symbol = 'km'
|
47
|
+
conf.dimension[:L] = 1
|
48
|
+
conf.from_si{|x| x/1000}
|
49
|
+
conf.to_si{|x| x*1000}
|
50
|
+
end
|
51
|
+
|
52
|
+
`conf.from_si`と`conf.to_si`で、SI基本単位で表した場合の変換式を設定します。
|
53
|
+
|
54
|
+
Unit#cast
|
55
|
+
----------------------
|
56
|
+
1 mi = 1.609344 km
|
57
|
+
のような関係の単位は、
|
58
|
+
|
59
|
+
mi = km.cast('mi', 1.609344)
|
60
|
+
|
61
|
+
で生成できます。
|
62
|
+
ただし、n倍だけの関係に限ります。
|
63
|
+
℃と℉のような関係の場合は`Unit.new`で新たに生成して下さい。
|
64
|
+
|
65
|
+
Unit<<, Unit[], Unit[]=
|
66
|
+
----------------------
|
67
|
+
`Unit << unit`で、`unit`を基本単位として登録します。
|
68
|
+
基本単位として登録することで、`Unit[]`から組立単位が自動的に導出されます。
|
69
|
+
|
70
|
+
NumericWith::Unit << km
|
71
|
+
NumericWith::Unit << NumericWith::Unit.new do |conf|
|
72
|
+
conf.symbol = 'hr'
|
73
|
+
conf.dimension[:T] = 1
|
74
|
+
conf.from_si{|x| x/60/60}
|
75
|
+
conf.to_si{|x| x*60*60}
|
76
|
+
end
|
77
|
+
|
78
|
+
puts NumericWith::Unit['km2'].symbol #=> km2
|
79
|
+
puts NumericWith::Unit['km/hr'].symbol #=> km/(hr)
|
80
|
+
|
81
|
+
基本単位として登録されている単位は、`Unit.list`で得られます。
|
82
|
+
|
83
|
+
また`Unit[]=`で単位の変換と基本単位として登録を同時に行えます。
|
84
|
+
|
85
|
+
NumericWith::Unit['kph'] = 'km/hr'
|
86
|
+
NumericWith::Unit['ua'] = 1.495978706916e8, 'm'
|
87
|
+
|
88
|
+
----
|
89
|
+
基本的な単位は以下のファイルで定義済みです。
|
90
|
+
適宜`require`してください。
|
91
|
+
|
92
|
+
* 'numeric_with_unit/unit_definition/base' (SI単位、SI組立単位およびSI併用単位を定義。デフォルトで`require`されます。)
|
93
|
+
* 'numeric_with_unit/unit_definition/common' (独断と偏見によりcommonと認定された単位。デフォルトで`require`されます。)
|
94
|
+
* 'numeric_with_unit/unit_definition/cgs' (未完成)
|
95
|
+
* 'numeric_with_unit/unit_definition/imperial' (未完成)
|
96
|
+
* 'numeric_with_unit/unit_definition/natural' (未完成)
|
97
|
+
|
98
|
+
|
99
|
+
class NumericWithUnit
|
100
|
+
======================
|
101
|
+
単位の情報を持った数値を表すクラスです。
|
102
|
+
|
103
|
+
単位換算したり足したり引いたり掛けたり割ったり累乗したりできます。
|
104
|
+
|
105
|
+
NumericWithUnit.new(value, unit)
|
106
|
+
----------------------
|
107
|
+
valueの数値とunitの単位を持つNumericWithUnitオブジェクトを返します。
|
108
|
+
unitには単位を表す文字列またはUnitクラスのオブジェクトを渡します。
|
109
|
+
|
110
|
+
Numeric#to_nwu(unit), Fixnum#to_nwu(unit), Bignum#to_nwu(unit)
|
111
|
+
----------------------
|
112
|
+
NumericWithUnit.new(self, unit)を返します。
|
113
|
+
|
114
|
+
NumericWithUnit#value
|
115
|
+
----------------------
|
116
|
+
数値を返します。
|
117
|
+
|
118
|
+
NumericWithUnit#unit
|
119
|
+
----------------------
|
120
|
+
Unitオブジェクトを返します。
|
121
|
+
|
122
|
+
NumericWithUnit#\[\](new_unit), NumericWithUnit#to_nwu(new_unit)
|
123
|
+
----------------------
|
124
|
+
new_unitに変換したNumericWithUnitオブジェクトを返します。
|
125
|
+
|
126
|
+
selfと次元の異なる単位を指定した場合は、NumericWithUnit::DimensionErrorが発生します。
|
127
|
+
|
128
|
+
NumericWithUnit#+(other), NumericWithUnit#-(other)
|
129
|
+
----------------------
|
130
|
+
otherがNumericWithUnitクラスの場合、selfの単位に変換し数値を加減したNumericWithUnitオブジェクトを返します。
|
131
|
+
otherがNumericWithUnitクラスでない場合、otherを無次元のNumericWithUnitにした上で加減します。
|
132
|
+
|
133
|
+
ohterとselfの次元が異なる場合は、NumericWithUnit#DimensionErrorが発生します。
|
134
|
+
|
135
|
+
NumericWithUnit#*(ohter), NumerichWithUnit#/(other)
|
136
|
+
----------------------
|
137
|
+
otherがNumericWithUnitクラスの場合、selfとotherの組立単位を持つ、数値を乗除したNumericWithUnitオブジェクトを返します。
|
138
|
+
otherがNumericWithUnitクラスでない場合、otherを無次元のNumericWithUnitにした上で乗除します。
|
139
|
+
|
140
|
+
NumericWithUnit#**(num)
|
141
|
+
----------------------
|
142
|
+
selfの単位をnum乗した組立単位を持つ、数値をnum乗したNumericWithUnitオブジェクトを返します。
|
143
|
+
|
144
|
+
|
145
|
+
単位を表す文字列のフォーマット
|
146
|
+
======================
|
147
|
+
Unit[]や、NumericWithUnit#[]には、単位を表す文字列を渡すことができます。
|
148
|
+
例を示します。
|
149
|
+
|
150
|
+
- m
|
151
|
+
- cm
|
152
|
+
- m2
|
153
|
+
- kW.hr
|
154
|
+
- kg/cm2
|
155
|
+
- m.s-1
|
156
|
+
- J/kg/K
|
157
|
+
- kcal/(hr.m2.℃)
|
158
|
+
|
159
|
+
先頭に接頭辞、末尾に指数をつけた基本単位を、"."または"/"で繋いだ形で表記します。
|
160
|
+
"()"で基本単位として括ることもできます。
|
161
|
+
|
162
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'numeric_with_unit'
|
4
|
+
|
5
|
+
class Fixnum
|
6
|
+
def to_nwu(unit)
|
7
|
+
NumericWithUnit.new(self, unit)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Bignum
|
12
|
+
def to_nwu(unit)
|
13
|
+
NumericWithUnit.new(self, unit)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Numeric
|
18
|
+
def to_nwu(unit)
|
19
|
+
NumericWithUnit.new(self, unit)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class String
|
24
|
+
def to_nwu(mthd=:to_r)
|
25
|
+
# TODO: 適当なのでもう少しいい感じに。いい感じに
|
26
|
+
m = self.match /.*?(?=[\s\(\[])/
|
27
|
+
value = m.to_s
|
28
|
+
unit = m.post_match.strip.gsub(/^\[|\]$/, '')
|
29
|
+
NumericWithUnit.new(value.__send__(mthd), unit)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -106,10 +106,11 @@ class NumericWithUnit
|
|
106
106
|
# class methods
|
107
107
|
|
108
108
|
# create new unit from derivation _(for internal use)_ .
|
109
|
-
def self.derive
|
109
|
+
def self.derive #(block)
|
110
110
|
derivation = Hash.new(0)
|
111
111
|
yield(derivation)
|
112
112
|
return Unit.new if derivation.empty?
|
113
|
+
|
113
114
|
derivation.delete_if{|k,v| k.symbol.nil?}
|
114
115
|
|
115
116
|
# constructing symbol
|
@@ -117,7 +118,7 @@ class NumericWithUnit
|
|
117
118
|
syms_pos = h.select{|u,v| v > 0}.map{|u,v| u.symbol + (v.abs>1 ? v.abs.to_s : '')}
|
118
119
|
syms_neg = h.select{|u,v| v < 0}.map{|u,v| u.symbol + (v.abs>1 ? v.abs.to_s : '')}
|
119
120
|
symbol = syms_pos.join('.')
|
120
|
-
symbol += '/' + (syms_neg.size
|
121
|
+
symbol += '/' + (syms_neg.size>1 ? "(#{syms_neg.join('.')})" : "#{syms_neg.first}") unless syms_neg.empty?
|
121
122
|
|
122
123
|
# constructing dimension
|
123
124
|
dimension = Hash.new(0)
|
@@ -132,7 +133,7 @@ class NumericWithUnit
|
|
132
133
|
prc = if v > 0
|
133
134
|
->(x){u.from_si(x)}
|
134
135
|
else
|
135
|
-
->(x){x.quo(u.from_si(1)-u.from_si(0))} # ℃とKの変換のような場合に、変換式の切片を消すため。変換式が線形じゃないケースは想定していない
|
136
|
+
->(x){x.quo(u.from_si(1)-u.from_si(0))} #FIXME: ℃とKの変換のような場合に、変換式の切片を消すため。変換式が線形じゃないケースは想定していない
|
136
137
|
end
|
137
138
|
[prc, v.abs]
|
138
139
|
}.map{|prc,v|
|
@@ -146,7 +147,7 @@ class NumericWithUnit
|
|
146
147
|
prc = if v > 0
|
147
148
|
->(x){u.to_si(x)}
|
148
149
|
else
|
149
|
-
->(x){x.quo(u.to_si(1)-u.to_si(0))} # ℃とKの変換のような場合に、変換式の切片を消すため。変換式が線形じゃないケースは想定していない
|
150
|
+
->(x){x.quo(u.to_si(1)-u.to_si(0))} #FIXME: ℃とKの変換のような場合に、変換式の切片を消すため。変換式が線形じゃないケースは想定していない
|
150
151
|
end
|
151
152
|
[prc, v.abs]
|
152
153
|
}.map{|prc,v|
|
@@ -183,7 +184,7 @@ class NumericWithUnit
|
|
183
184
|
|
184
185
|
# return base unit list.
|
185
186
|
def self.list
|
186
|
-
@@list
|
187
|
+
@@list
|
187
188
|
end
|
188
189
|
|
189
190
|
# add unit to base unit list.
|
@@ -307,7 +308,7 @@ class NumericWithUnit
|
|
307
308
|
rec[x, derivation, order]
|
308
309
|
end
|
309
310
|
else
|
310
|
-
raise StandardError,
|
311
|
+
raise StandardError, %(maybe bug in "numeric_with_unit" gem)
|
311
312
|
end
|
312
313
|
derivation
|
313
314
|
end
|
@@ -326,7 +327,7 @@ class NumericWithUnit
|
|
326
327
|
attr_reader :dimension, :derivation
|
327
328
|
|
328
329
|
def initialize(derivation=nil)
|
329
|
-
# Unit::Configとinitializeの役割が分離できていないので見なおせ
|
330
|
+
# TODO: Unit::Configとinitializeの役割が分離できていないので見なおせ
|
330
331
|
config = Config.new
|
331
332
|
yield(config) if block_given?
|
332
333
|
config.compile
|
@@ -358,12 +359,16 @@ class NumericWithUnit
|
|
358
359
|
@symbol
|
359
360
|
end
|
360
361
|
|
362
|
+
def inspect
|
363
|
+
"#<#{self.class}:[#{@symbol}] #{@dimension}>"
|
364
|
+
end
|
365
|
+
|
361
366
|
def to_si(value)
|
362
|
-
@to_si
|
367
|
+
@to_si.call(value)
|
363
368
|
end
|
364
369
|
|
365
370
|
def from_si(value)
|
366
|
-
@from_si
|
371
|
+
@from_si.call(value)
|
367
372
|
end
|
368
373
|
|
369
374
|
|
@@ -405,6 +410,7 @@ class NumericWithUnit
|
|
405
410
|
self.class.new
|
406
411
|
else
|
407
412
|
self.class.derive do |derivation|
|
413
|
+
# NOTE:
|
408
414
|
# ここto_iでOKか?v*numが整数じゃなければraiseすべき?→すべき→NumericWithUnitでやるべき?
|
409
415
|
# Unitでは整数じゃない次数の単位は許容すべきか否か→していい気がする
|
410
416
|
@derivation.each{|k, v| derivation[k] = (v*num).to_i}
|
@@ -412,6 +418,17 @@ class NumericWithUnit
|
|
412
418
|
end
|
413
419
|
end
|
414
420
|
|
421
|
+
|
422
|
+
def simplify
|
423
|
+
self.class.derive{|derivation|
|
424
|
+
@dimension.each do|d,o|
|
425
|
+
u = self.class.list.find{|u| u.dimension == {d => 1}} #TODO: find? ok?
|
426
|
+
raise NoUnitError, "No unit with #{{d=>1}} dimension is assined." unless u
|
427
|
+
derivation[u] = o
|
428
|
+
end
|
429
|
+
}
|
430
|
+
end
|
431
|
+
|
415
432
|
end
|
416
433
|
|
417
434
|
class Unit
|
@@ -48,7 +48,7 @@ class NumericWithUnit
|
|
48
48
|
# Thermodynamic Temperature
|
49
49
|
Unit << Unit.new do |conf|
|
50
50
|
conf.symbol = 'K'
|
51
|
-
conf.dimension[
|
51
|
+
conf.dimension[:THETA] = 1
|
52
52
|
conf.si = true
|
53
53
|
end
|
54
54
|
|
@@ -120,16 +120,16 @@ class NumericWithUnit
|
|
120
120
|
# Inductance
|
121
121
|
Unit['H'] = 'V.s/A'
|
122
122
|
|
123
|
-
# Temperature
|
124
|
-
Unit << Unit.new do |conf|
|
125
|
-
k = Unit['K']
|
126
|
-
intercept = "273.15".to_r
|
127
|
-
|
128
|
-
conf.symbol = '℃'
|
129
|
-
conf.dimension = k.dimension
|
130
|
-
conf.from_si{|x| k.from_si(x)-intercept}
|
131
|
-
conf.to_si{|x| k.to_si(x+intercept)}
|
132
|
-
end
|
123
|
+
# # Temperature
|
124
|
+
# Unit << Unit.new do |conf|
|
125
|
+
# k = Unit['K']
|
126
|
+
# intercept = "273.15".to_r
|
127
|
+
#
|
128
|
+
# conf.symbol = '℃'
|
129
|
+
# conf.dimension = k.dimension
|
130
|
+
# conf.from_si{|x| k.from_si(x)-intercept}
|
131
|
+
# conf.to_si{|x| k.to_si(x+intercept)}
|
132
|
+
# end
|
133
133
|
|
134
134
|
# Luminouse flux
|
135
135
|
Unit['lx'] = 'cd.sr'
|
File without changes
|
@@ -19,24 +19,24 @@ class NumericWithUnit
|
|
19
19
|
|
20
20
|
# Mass
|
21
21
|
Unit['ton'] = 1000, 'kg'
|
22
|
-
Unit['
|
23
|
-
Unit['
|
22
|
+
Unit['lb'] = "0.45359237".to_r, 'kg' # 常用ポンド
|
23
|
+
Unit['oz'] = "1/16".to_r, 'lb' # 常用オンス
|
24
24
|
|
25
25
|
# Electriccal Resistance
|
26
26
|
Unit['ohm'] = 'Ω'
|
27
27
|
|
28
28
|
# Temperature
|
29
|
-
Unit['degC'] = '℃'
|
29
|
+
# Unit['degC'] = '℃'
|
30
30
|
Unit['degR'] = "5/9".to_r, 'K'
|
31
|
-
Unit << Unit.new do |conf|
|
32
|
-
degr = Unit['degR']
|
33
|
-
intercept = "459.67".to_r
|
34
|
-
|
35
|
-
conf.symbol = 'degF'
|
36
|
-
conf.dimension = degr.dimension
|
37
|
-
conf.from_si{|x| degr.from_si(x)-intercept}
|
38
|
-
conf.to_si{|x| degr.to_si(x+intercept)}
|
39
|
-
end
|
31
|
+
# Unit << Unit.new do |conf|
|
32
|
+
# degr = Unit['degR']
|
33
|
+
# intercept = "459.67".to_r
|
34
|
+
#
|
35
|
+
# conf.symbol = 'degF'
|
36
|
+
# conf.dimension = degr.dimension
|
37
|
+
# conf.from_si{|x| degr.from_si(x)-intercept}
|
38
|
+
# conf.to_si{|x| degr.to_si(x+intercept)}
|
39
|
+
# end
|
40
40
|
|
41
41
|
# Length
|
42
42
|
Unit['Å'] = 10**-10, 'm'
|
@@ -48,7 +48,8 @@ class NumericWithUnit
|
|
48
48
|
|
49
49
|
# Volume
|
50
50
|
Unit['cc'] = 'cm3'
|
51
|
-
Unit['
|
51
|
+
Unit['gal'] = 231, 'in3' # 米液量ガロン
|
52
|
+
Unit['bbl'] = 42, 'gal' # 石油要バレル
|
52
53
|
|
53
54
|
# Force
|
54
55
|
Unit['kgf'] = "9.80665".to_r, 'N'
|
@@ -66,24 +67,25 @@ class NumericWithUnit
|
|
66
67
|
Unit['mHg'] = "1/1000".to_r, 'mmHg' # for compatible
|
67
68
|
Unit['mH2O'] = "9806.65".to_r, 'Pa'
|
68
69
|
Unit['mAq'] = 'mH2O'
|
69
|
-
Unit['psi'] =
|
70
|
-
|
71
|
-
# Guage圧の扱いどうしようか?
|
72
|
-
Unit << Unit.new do |conf|
|
73
|
-
pa = Unit['Pa']
|
74
|
-
atm = 101325
|
75
|
-
|
76
|
-
conf.symbol = 'PaG'
|
77
|
-
conf.dimension = pa.dimension
|
78
|
-
conf.from_si{|x| pa.from_si(x)-atm}
|
79
|
-
conf.to_si{|x| pa.to_si(x+atm)}
|
80
|
-
end
|
70
|
+
Unit['psi'] = 'lbf/in2'
|
71
|
+
|
72
|
+
# # Guage圧の扱いどうしようか?
|
73
|
+
# Unit << Unit.new do |conf|
|
74
|
+
# pa = Unit['Pa']
|
75
|
+
# atm = 101325
|
76
|
+
#
|
77
|
+
# conf.symbol = 'PaG'
|
78
|
+
# conf.dimension = pa.dimension
|
79
|
+
# conf.from_si{|x| pa.from_si(x)-atm}
|
80
|
+
# conf.to_si{|x| pa.to_si(x+atm)}
|
81
|
+
# end
|
81
82
|
|
82
83
|
# Speed
|
83
84
|
Unit['kph'] = 'km/hr'
|
84
85
|
|
85
86
|
# Flowrate
|
86
87
|
Unit['lpm'] = 'L/min'
|
88
|
+
Unit['CMH'] = 'm3/hr'
|
87
89
|
|
88
90
|
# Viscosity
|
89
91
|
Unit['P'] = "1/10".to_r, 'Pa.s'
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
#
|
4
|
+
# 変換に対応しきれていない単位
|
5
|
+
# 四則演算を交える場合に要注意
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'numeric_with_unit/unit_definition/base'
|
9
|
+
|
10
|
+
class NumericWithUnit
|
11
|
+
# Temperature
|
12
|
+
Unit << Unit.new do |conf|
|
13
|
+
k = Unit['K']
|
14
|
+
intercept = "273.15".to_r
|
15
|
+
|
16
|
+
conf.symbol = '℃'
|
17
|
+
conf.dimension = k.dimension
|
18
|
+
conf.from_si{|x| k.from_si(x)-intercept}
|
19
|
+
conf.to_si{|x| k.to_si(x+intercept)}
|
20
|
+
end
|
21
|
+
|
22
|
+
Unit['degC'] = '℃'
|
23
|
+
|
24
|
+
Unit << Unit.new do |conf|
|
25
|
+
degr = Unit['degR']
|
26
|
+
intercept = "459.67".to_r
|
27
|
+
|
28
|
+
conf.symbol = 'degF'
|
29
|
+
conf.dimension = degr.dimension
|
30
|
+
conf.from_si{|x| degr.from_si(x)-intercept}
|
31
|
+
conf.to_si{|x| degr.to_si(x+intercept)}
|
32
|
+
end
|
33
|
+
|
34
|
+
# Pressure
|
35
|
+
Unit << Unit.new do |conf|
|
36
|
+
pa = Unit['Pa']
|
37
|
+
atm = 101325
|
38
|
+
|
39
|
+
conf.symbol = 'PaG'
|
40
|
+
conf.dimension = pa.dimension
|
41
|
+
conf.from_si{|x| pa.from_si(x)-atm}
|
42
|
+
conf.to_si{|x| pa.to_si(x+atm)}
|
43
|
+
end
|
44
|
+
end
|
File without changes
|
File without changes
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
3
|
# 123.m2.K_W のように書けるようにします。
|
4
|
+
# 123.cP.mPa.s のように単位の換算(cP -> mPa.s)も可能です。
|
4
5
|
# method_missing をオーバーライドします。
|
5
6
|
|
6
7
|
require 'numeric_with_unit'
|
@@ -9,7 +10,7 @@ class NumericWithUnit
|
|
9
10
|
def method_missing(name, *args)
|
10
11
|
if args.empty?
|
11
12
|
unit_str = name.to_s.gsub('_', '/')
|
12
|
-
|
13
|
+
resolve_unit_chain(Unit[unit_str])
|
13
14
|
else
|
14
15
|
raise Unit::NoUnitError
|
15
16
|
end
|
@@ -18,20 +19,21 @@ class NumericWithUnit
|
|
18
19
|
end
|
19
20
|
|
20
21
|
attr_writer :unit_chain
|
22
|
+
protected :unit_chain=
|
21
23
|
|
22
24
|
private
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
def resolve_unit_chain(unit)
|
26
|
+
unit_chain = @unit_chain || []
|
27
|
+
unit_chain.map!{|nwu, chained_unit| [nwu, chained_unit * unit]}
|
28
|
+
unit_chain << [self, unit]
|
27
29
|
|
28
|
-
if i =
|
29
|
-
nwu,
|
30
|
-
nwu
|
30
|
+
if i = unit_chain.index{|nwu, chained_unit| nwu.unit.dimension_equal? chained_unit}
|
31
|
+
nwu, chained_unit = *unit_chain[i]
|
32
|
+
nwu.convert(chained_unit)
|
31
33
|
else
|
32
|
-
|
33
|
-
|
34
|
-
|
34
|
+
newnwu = self.class.new(@value, @unit*unit)
|
35
|
+
newnwu.unit_chain = unit_chain
|
36
|
+
newnwu
|
35
37
|
end
|
36
38
|
end
|
37
39
|
end
|
@@ -42,7 +44,7 @@ class NumericWithUnit
|
|
42
44
|
def method_missing(name, *args)
|
43
45
|
if args.empty?
|
44
46
|
unit_str = name.to_s.gsub('_', '/')
|
45
|
-
self.
|
47
|
+
self.to_f.to_nwu(unit_str) # util2は利便性優先なのでto_fしてしまいます
|
46
48
|
else
|
47
49
|
raise Unit::NoUnitError
|
48
50
|
end
|
data/lib/numeric_with_unit.rb
CHANGED
@@ -4,68 +4,84 @@ require 'numeric_with_unit/unit'
|
|
4
4
|
|
5
5
|
class NumericWithUnit
|
6
6
|
include Comparable
|
7
|
-
|
7
|
+
|
8
8
|
attr_reader :value, :unit
|
9
|
-
|
9
|
+
|
10
10
|
def initialize(value, unit)
|
11
11
|
@value = value
|
12
12
|
@unit = unit.is_a?(Unit) ? unit : Unit[unit]
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
# Return String for inspect
|
16
16
|
def inspect
|
17
|
-
"#{@value.inspect} [#{@unit.symbol}] #{unit.dimension.inspect}"
|
17
|
+
"#{@value.inspect} [#{@unit.symbol}] #{@unit.dimension.inspect}"
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
# Return String with value and unit symbol
|
21
21
|
def to_s
|
22
22
|
"#{@value.to_s} #{@unit.symbol}"
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
# If ohter is NumericWithUnit and same dimension, comparing value with converting to si.
|
26
26
|
# Else return nil.
|
27
27
|
def <=>(other)
|
28
28
|
if other.is_a?(self.class) and @unit.dimension_equal? other.unit
|
29
|
-
|
29
|
+
value_si <=> other.value_si
|
30
30
|
end
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
|
+
def ===(other)
|
34
|
+
self.<=>(other) == 0
|
35
|
+
end
|
36
|
+
|
33
37
|
# Return succed value with same unit.
|
34
38
|
def succ
|
35
39
|
self.class.new(@value.succ, @unit)
|
36
40
|
end
|
37
|
-
|
41
|
+
|
38
42
|
# Return value.to_i
|
39
43
|
def to_i
|
40
44
|
@value.to_i
|
41
45
|
end
|
42
|
-
|
46
|
+
|
43
47
|
# Return value.to_f
|
44
48
|
def to_f
|
45
49
|
@value.to_f
|
46
50
|
end
|
47
|
-
|
48
|
-
# Return
|
49
|
-
def
|
51
|
+
|
52
|
+
# Return value in si
|
53
|
+
def value_si
|
54
|
+
@unit.to_si(@value)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Convert to given unit
|
58
|
+
def convert(unit)
|
50
59
|
new_unit = unit.is_a?(Unit) ? unit : Unit[unit]
|
51
|
-
|
60
|
+
|
52
61
|
unless @unit.dimension_equal? new_unit
|
53
62
|
raise DimensionError, "Dimensions are different between #{@unit.symbol}#{@unit.dimension} #{new_unit.symbol}#{new_unit.dimension}"
|
54
63
|
end
|
55
|
-
|
64
|
+
|
56
65
|
new_value = new_unit.from_si(@unit.to_si(@value))
|
57
66
|
self.class.new(new_value, new_unit)
|
58
67
|
end
|
59
|
-
alias :
|
60
|
-
|
68
|
+
alias :to_nwu :convert
|
69
|
+
alias :[] :convert
|
70
|
+
|
71
|
+
# Convert to simple unit
|
72
|
+
def simplify
|
73
|
+
convert(@unit.simplify)
|
74
|
+
end
|
75
|
+
|
76
|
+
|
61
77
|
def +@
|
62
78
|
self
|
63
79
|
end
|
64
|
-
|
80
|
+
|
65
81
|
def -@
|
66
82
|
self.class.new(-@value, @unit)
|
67
83
|
end
|
68
|
-
|
84
|
+
|
69
85
|
def +(other)
|
70
86
|
nwu = if other.is_a? self.class
|
71
87
|
other
|
@@ -74,11 +90,11 @@ class NumericWithUnit
|
|
74
90
|
end
|
75
91
|
add_with_other_unit(nwu)
|
76
92
|
end
|
77
|
-
|
93
|
+
|
78
94
|
def -(other)
|
79
95
|
self + (-other)
|
80
96
|
end
|
81
|
-
|
97
|
+
|
82
98
|
def *(other)
|
83
99
|
case other
|
84
100
|
when self.class
|
@@ -87,7 +103,7 @@ class NumericWithUnit
|
|
87
103
|
self.class.new(@value*other, @unit)
|
88
104
|
end
|
89
105
|
end
|
90
|
-
|
106
|
+
|
91
107
|
def /(other)
|
92
108
|
case other
|
93
109
|
when self.class
|
@@ -96,7 +112,7 @@ class NumericWithUnit
|
|
96
112
|
self.class.new(@value/other, @unit)
|
97
113
|
end
|
98
114
|
end
|
99
|
-
|
115
|
+
|
100
116
|
def coerce(other)
|
101
117
|
if other.is_a?(self.class)
|
102
118
|
[other, self]
|
@@ -104,25 +120,47 @@ class NumericWithUnit
|
|
104
120
|
[self.class.new(other, Unit.new), self]
|
105
121
|
end
|
106
122
|
end
|
107
|
-
|
123
|
+
|
108
124
|
def **(num)
|
109
125
|
# Dimension Check
|
110
|
-
@unit.derivation.
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
126
|
+
if @unit.derivation.all?{|k,v| o = v * num; o.to_i == o} # TODO: 整数かどうかの判定方法いいのこれで
|
127
|
+
self.class.new(@value**num, @unit**num)
|
128
|
+
else
|
129
|
+
nu = @unit.simplify
|
130
|
+
if nu.derivation.all?{|k,v| o = v * num; o.to_i == o}
|
131
|
+
nv = nu.from_si(@unit.to_si(@value))
|
132
|
+
self.class.new(nv ** num, nu**num)
|
133
|
+
else
|
134
|
+
raise DimensionError, "All derivating units order multiplied #{num} must be integer"
|
135
|
+
end
|
136
|
+
end
|
116
137
|
end
|
117
|
-
|
138
|
+
|
118
139
|
def root(num)
|
119
140
|
self**(Rational(1,num))
|
120
141
|
end
|
121
142
|
def sqrt; root(2) end # 平方根
|
122
143
|
def cbrt; root(3) end # 立方根
|
123
|
-
|
144
|
+
|
145
|
+
def ceil
|
146
|
+
self.class.new(@value.ceil, @unit)
|
147
|
+
end
|
148
|
+
|
149
|
+
def floor
|
150
|
+
self.class.new(@value.floor, @unit)
|
151
|
+
end
|
152
|
+
|
153
|
+
def round
|
154
|
+
self.class.new(@value.round, @unit)
|
155
|
+
end
|
156
|
+
|
157
|
+
def truncate
|
158
|
+
self.class.new(@value.truncate, @unit)
|
159
|
+
end
|
160
|
+
|
161
|
+
|
124
162
|
private
|
125
|
-
|
163
|
+
|
126
164
|
def add_with_other_unit(other)
|
127
165
|
if @unit.dimension_equal? other.unit
|
128
166
|
v1 = @unit.to_si(@value)
|
@@ -133,12 +171,12 @@ class NumericWithUnit
|
|
133
171
|
raise DimensionError, "Dimensions are different between #{@unit.dimension} #{other.unit.dimension}"
|
134
172
|
end
|
135
173
|
end
|
136
|
-
|
174
|
+
|
137
175
|
def multiply_with_other_unit(other)
|
138
176
|
onwu = adjust_other_unit(other)
|
139
177
|
self.class.new(@value * onwu.value, @unit * onwu.unit)
|
140
178
|
end
|
141
|
-
|
179
|
+
|
142
180
|
def devide_with_other_unit(other)
|
143
181
|
onwu = adjust_other_unit(other)
|
144
182
|
self.class.new(@value / onwu.value, @unit / onwu.unit)
|
@@ -156,7 +194,7 @@ class NumericWithUnit
|
|
156
194
|
other
|
157
195
|
end
|
158
196
|
end
|
159
|
-
|
197
|
+
|
160
198
|
end
|
161
199
|
|
162
200
|
|
@@ -167,37 +205,8 @@ end
|
|
167
205
|
|
168
206
|
|
169
207
|
|
170
|
-
|
171
|
-
def to_nwu(unit)
|
172
|
-
NumericWithUnit.new(self, unit)
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
class Bignum
|
177
|
-
def to_nwu(unit)
|
178
|
-
NumericWithUnit.new(self, unit)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
class Numeric
|
183
|
-
def to_nwu(unit)
|
184
|
-
NumericWithUnit.new(self, unit)
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
class String
|
189
|
-
def to_nwu(mthd=:to_r)
|
190
|
-
# 適当
|
191
|
-
m = self.match /.*?(?=[\s\(\[])/
|
192
|
-
value = m.to_s
|
193
|
-
unit = m.post_match.strip.gsub(/^\[|\]$/, '')
|
194
|
-
NumericWithUnit.new(value.__send__(mthd), unit)
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
|
208
|
+
require 'numeric_with_unit/core_ext'
|
199
209
|
|
200
210
|
# unit definition
|
201
211
|
require 'numeric_with_unit/unit_definition/base'
|
202
212
|
require 'numeric_with_unit/unit_definition/common'
|
203
|
-
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: numeric_with_unit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- diaphragm
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: This gem provide NumericWithUnit class to calculate numeric with unit
|
14
14
|
of measurement.
|
@@ -17,11 +17,15 @@ executables: []
|
|
17
17
|
extensions: []
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
|
+
- LICENSE
|
21
|
+
- README.md
|
20
22
|
- lib/numeric_with_unit.rb
|
23
|
+
- lib/numeric_with_unit/core_ext.rb
|
21
24
|
- lib/numeric_with_unit/unit.rb
|
22
25
|
- lib/numeric_with_unit/unit_definition/base.rb
|
23
26
|
- lib/numeric_with_unit/unit_definition/cgs.rb
|
24
27
|
- lib/numeric_with_unit/unit_definition/common.rb
|
28
|
+
- lib/numeric_with_unit/unit_definition/deprecated.rb
|
25
29
|
- lib/numeric_with_unit/unit_definition/imperial.rb
|
26
30
|
- lib/numeric_with_unit/unit_definition/natural.rb
|
27
31
|
- lib/numeric_with_unit/util.rb
|
@@ -46,7 +50,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
46
50
|
version: '0'
|
47
51
|
requirements: []
|
48
52
|
rubyforge_project:
|
49
|
-
rubygems_version: 2.
|
53
|
+
rubygems_version: 2.5.1
|
50
54
|
signing_key:
|
51
55
|
specification_version: 4
|
52
56
|
summary: Numerical calculation with unit of measurement
|