unitwise 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,119 +3,119 @@
3
3
  :symbol: Y
4
4
  :primary_code: Y
5
5
  :secondary_code: YA
6
- :scalar: 1e24
6
+ :scalar: 1000000000000000000000000
7
7
  - :names: zetta
8
8
  :symbol: Z
9
9
  :primary_code: Z
10
10
  :secondary_code: ZA
11
- :scalar: 1e21
11
+ :scalar: 1000000000000000000000
12
12
  - :names: exa
13
13
  :symbol: E
14
14
  :primary_code: E
15
15
  :secondary_code: EX
16
- :scalar: 1e18
16
+ :scalar: 1000000000000000000
17
17
  - :names: peta
18
18
  :symbol: P
19
19
  :primary_code: P
20
20
  :secondary_code: PT
21
- :scalar: 1e15
21
+ :scalar: 1000000000000000
22
22
  - :names: tera
23
23
  :symbol: T
24
24
  :primary_code: T
25
25
  :secondary_code: TR
26
- :scalar: 1e12
26
+ :scalar: 1000000000000
27
27
  - :names: giga
28
28
  :symbol: G
29
29
  :primary_code: G
30
30
  :secondary_code: GA
31
- :scalar: 1e9
31
+ :scalar: 1000000000
32
32
  - :names: mega
33
33
  :symbol: M
34
34
  :primary_code: M
35
35
  :secondary_code: MA
36
- :scalar: 1e6
36
+ :scalar: 1000000
37
37
  - :names: kilo
38
38
  :symbol: k
39
39
  :primary_code: k
40
40
  :secondary_code: K
41
- :scalar: 1e3
41
+ :scalar: 1000
42
42
  - :names: hecto
43
43
  :symbol: h
44
44
  :primary_code: h
45
45
  :secondary_code: H
46
- :scalar: 1e2
46
+ :scalar: 100
47
47
  - :names: deka
48
48
  :symbol: da
49
49
  :primary_code: da
50
50
  :secondary_code: DA
51
- :scalar: 1e1
51
+ :scalar: 10
52
52
  - :names: deci
53
53
  :symbol: d
54
54
  :primary_code: d
55
55
  :secondary_code: D
56
- :scalar: 1e-1
56
+ :scalar: !ruby/object:BigDecimal 18:0.1e0
57
57
  - :names: centi
58
58
  :symbol: c
59
59
  :primary_code: c
60
60
  :secondary_code: C
61
- :scalar: 1e-2
61
+ :scalar: !ruby/object:BigDecimal 18:0.1e-1
62
62
  - :names: milli
63
63
  :symbol: m
64
64
  :primary_code: m
65
65
  :secondary_code: M
66
- :scalar: 1e-3
66
+ :scalar: !ruby/object:BigDecimal 18:0.1e-2
67
67
  - :names: micro
68
68
  :symbol: μ
69
69
  :primary_code: u
70
70
  :secondary_code: U
71
- :scalar: 1e-6
71
+ :scalar: !ruby/object:BigDecimal 18:0.1e-5
72
72
  - :names: nano
73
73
  :symbol: n
74
74
  :primary_code: n
75
75
  :secondary_code: N
76
- :scalar: 1e-9
76
+ :scalar: !ruby/object:BigDecimal 18:0.1e-8
77
77
  - :names: pico
78
78
  :symbol: p
79
79
  :primary_code: p
80
80
  :secondary_code: P
81
- :scalar: 1e-12
81
+ :scalar: !ruby/object:BigDecimal 18:0.1e-11
82
82
  - :names: femto
83
83
  :symbol: f
84
84
  :primary_code: f
85
85
  :secondary_code: F
86
- :scalar: 1e-15
86
+ :scalar: !ruby/object:BigDecimal 18:0.1e-14
87
87
  - :names: atto
88
88
  :symbol: a
89
89
  :primary_code: a
90
90
  :secondary_code: A
91
- :scalar: 1e-18
91
+ :scalar: !ruby/object:BigDecimal 18:0.1e-17
92
92
  - :names: zepto
93
93
  :symbol: z
94
94
  :primary_code: z
95
95
  :secondary_code: ZO
96
- :scalar: 1e-21
96
+ :scalar: !ruby/object:BigDecimal 18:0.1e-20
97
97
  - :names: yocto
98
98
  :symbol: y
99
99
  :primary_code: y
100
100
  :secondary_code: YO
101
- :scalar: 1e-24
101
+ :scalar: !ruby/object:BigDecimal 18:0.1e-23
102
102
  - :names: kibi
103
103
  :symbol: Ki
104
104
  :primary_code: Ki
105
105
  :secondary_code: KIB
106
- :scalar: '1024'
106
+ :scalar: 1024
107
107
  - :names: mebi
108
108
  :symbol: Mi
109
109
  :primary_code: Mi
110
110
  :secondary_code: MIB
111
- :scalar: '1048576'
111
+ :scalar: 1048576
112
112
  - :names: gibi
113
113
  :symbol: Gi
114
114
  :primary_code: Gi
115
115
  :secondary_code: GIB
116
- :scalar: '1073741824'
116
+ :scalar: 1073741824
117
117
  - :names: tebi
118
118
  :symbol: Ti
119
119
  :primary_code: Ti
120
120
  :secondary_code: TIB
121
- :scalar: '1099511627776'
121
+ :scalar: 1099511627776
@@ -8,6 +8,7 @@ require 'bigdecimal'
8
8
  require 'unitwise/version'
9
9
  require 'unitwise/base'
10
10
  require 'unitwise/compatible'
11
+ require 'unitwise/number'
11
12
  require 'unitwise/expression'
12
13
  require 'unitwise/scale'
13
14
  require 'unitwise/functional'
@@ -103,11 +103,11 @@ module Unitwise
103
103
  # @return [Numeric]
104
104
  # @api public
105
105
  def scalar(magnitude = 1)
106
- base? ? BigDecimal(magnitude.to_s) : scale.scalar(magnitude)
106
+ base? ? magnitude : scale.scalar(magnitude)
107
107
  end
108
108
 
109
109
  def magnitude(scalar = scalar())
110
- special? ? scale.magnitude(scalar) : BigDecimal('1')
110
+ special? ? scale.magnitude(scalar) : 1
111
111
  end
112
112
 
113
113
  # An atom may have a complex scale with several base atoms at various
@@ -22,6 +22,14 @@ module Unitwise
22
22
  5.0 / 9.0 * (x + 459.67)
23
23
  end
24
24
 
25
+ def self.to_degre(x)
26
+ 4.0 * x / 5.0 - 218.52
27
+ end
28
+
29
+ def self.from_degre(x)
30
+ 5.0 / 4.0 * (x + 218.52)
31
+ end
32
+
25
33
  def self.to_hpX(x)
26
34
  -log10(x)
27
35
  end
@@ -129,7 +129,7 @@ module Unitwise
129
129
  # measurement.to_r # => (17/4)
130
130
  # @api public
131
131
  def to_r
132
- Rational(value)
132
+ Number.rationalize(value)
133
133
  end
134
134
 
135
135
  # Will attempt to convert to a unit by method name.
@@ -156,10 +156,6 @@ module Unitwise
156
156
  self.class.new(*args)
157
157
  end
158
158
 
159
- # Set the value for the measurement.
160
- # @api private
161
- attr_writer :value
162
-
163
159
  # Determine value of the unit after conversion to another unit
164
160
  # @api private
165
161
  def converted_value(other_unit)
@@ -0,0 +1,62 @@
1
+ module Unitwise
2
+ class Number
3
+ # Attempts to coerce a value to the simplest Numeric that fully expresses
4
+ # it's value. For instance a value of 1.0 would return 1, a value of
5
+ # #<BigDecimal:7f9558d559b8,'0.45E1',18(18)> would return 4.5.
6
+ # @api public
7
+ # @param value [Integer, Float, Rational, String, BigDecimal]
8
+ # @return [Integer, Float, Rational, BigDecimal]
9
+ def self.simplify(value)
10
+ case value
11
+ when Integer
12
+ value
13
+ when Float
14
+ (i = value.to_i) == value ? i : value
15
+ when Rational
16
+ if (i = value.to_i) == value
17
+ i
18
+ elsif (f = value.to_f) && f.to_r == value
19
+ f
20
+ else
21
+ value
22
+ end
23
+ else # String, BigDecimal, Other
24
+ s = value.is_a?(String) ? value : value.to_s
25
+ d = value.is_a?(BigDecimal) ? value : BigDecimal(s)
26
+ if (i = d.to_i) == d
27
+ i
28
+ elsif (f = d.to_f) == d
29
+ f
30
+ else
31
+ d
32
+ end
33
+ end
34
+ end
35
+
36
+ # Coerces a string-like number to a BigDecimal or Integer as appropriate
37
+ # @api public
38
+ # @param value Something that can be represented as a string number
39
+ # @return [Integer, BigDecimal]
40
+ def self.coefficify(value)
41
+ d = BigDecimal.new(value.to_s)
42
+ if (i = d.to_i) == d
43
+ i
44
+ else
45
+ d
46
+ end
47
+ end
48
+
49
+ # Coerce a numeric to a Rational, but avoid inaccurate conversions by
50
+ # jruby. More details here: https://github.com/jruby/jruby/issues/4711.
51
+ # @api public
52
+ # @param number [Numeric]
53
+ # @return Rational
54
+ def self.rationalize(number)
55
+ if number.is_a?(BigDecimal) && RUBY_PLATFORM == 'java'
56
+ number.to_s.to_r
57
+ else
58
+ number.to_r
59
+ end
60
+ end
61
+ end
62
+ end
@@ -14,11 +14,5 @@ module Unitwise
14
14
  def self.data_file
15
15
  Unitwise.data_file 'prefix'
16
16
  end
17
-
18
- # Set the scalar value for the prefix, always as a BigDecimal
19
- # @api semipublic
20
- def scalar=(value)
21
- @scalar = BigDecimal(value.to_s)
22
- end
23
17
  end
24
18
  end
@@ -30,10 +30,6 @@ module Unitwise
30
30
  unit.atoms
31
31
  end
32
32
 
33
- def value=(value)
34
- @value = BigDecimal(value.to_s)
35
- end
36
-
37
33
  # List the terms associated with this scale's unit.
38
34
  # @return [Array]
39
35
  # @api public
@@ -56,7 +52,7 @@ module Unitwise
56
52
  if special?
57
53
  unit.scalar(magnitude)
58
54
  else
59
- value * unit.scalar
55
+ Number.rationalize(value) * Number.rationalize(unit.scalar)
60
56
  end
61
57
  end
62
58
 
@@ -95,17 +91,7 @@ module Unitwise
95
91
  # @return [Numeric]
96
92
  # @api public
97
93
  def simplified_value
98
- if value.is_a?(Integer)
99
- value
100
- elsif (i = Integer(value)) == value
101
- i
102
- elsif value.is_a?(Float) || value.is_a?(Rational)
103
- value
104
- elsif (f = Float(value)) == value
105
- f
106
- else
107
- value
108
- end
94
+ Unitwise::Number.simplify(value)
109
95
  end
110
96
  memoize :simplified_value
111
97
 
@@ -12,7 +12,7 @@ module Unitwise::Standard
12
12
  end
13
13
 
14
14
  def value
15
- attributes["function"]["@value"].to_f
15
+ Unitwise::Number.simplify(attributes["function"]["@value"])
16
16
  end
17
17
 
18
18
  def unit
@@ -32,4 +32,4 @@ module Unitwise::Standard
32
32
  end
33
33
 
34
34
  end
35
- end
35
+ end
@@ -6,12 +6,13 @@ module Unitwise::Standard
6
6
  end
7
7
 
8
8
  def scale
9
- attributes["value"].attributes["value"]
9
+ Unitwise::Number.coefficify(
10
+ attributes.fetch('value').attributes.fetch('value')
11
+ )
10
12
  end
11
13
 
12
14
  def to_hash
13
15
  super().merge(:scalar => scale)
14
16
  end
15
-
16
17
  end
17
- end
18
+ end
@@ -7,7 +7,7 @@ module Unitwise::Standard
7
7
  end
8
8
 
9
9
  def value
10
- nori.attributes["value"].to_f
10
+ Unitwise::Number.coefficify(nori.attributes.fetch('value'))
11
11
  end
12
12
 
13
13
  def primary_unit_code
@@ -22,4 +22,4 @@ module Unitwise::Standard
22
22
  {:value => value, :unit_code => primary_unit_code}
23
23
  end
24
24
  end
25
- end
25
+ end
@@ -59,7 +59,7 @@ module Unitwise
59
59
  # @param magnitude [Numeric] The magnitude to calculate the scalar for.
60
60
  # @return [Numeric] The unitless linear scalar value.
61
61
  # @api public
62
- def scalar(magnitude = 1.0)
62
+ def scalar(magnitude = 1)
63
63
  calculate(atom ? atom.scalar(magnitude) : magnitude)
64
64
  end
65
65
 
@@ -68,7 +68,7 @@ module Unitwise
68
68
  # @return [Numeric] The magnitude on this scale.
69
69
  # @api public
70
70
  def magnitude(scalar = scalar())
71
- calculate(atom ? atom.magnitude(scalar) : 1.0)
71
+ calculate(atom ? atom.magnitude(scalar) : 1)
72
72
  end
73
73
 
74
74
  # The base units this term is derived from
@@ -86,8 +86,8 @@ module Unitwise
86
86
  # @param magnitude [Numeric] An optional magnitude on this unit's scale.
87
87
  # @return [Numeric] A scalar value on a linear scale
88
88
  # @api public
89
- def scalar(magnitude = 1.0)
90
- terms.reduce(1.0) do |prod, term|
89
+ def scalar(magnitude = 1)
90
+ terms.reduce(1) do |prod, term|
91
91
  prod * term.scalar(magnitude)
92
92
  end
93
93
  end
@@ -98,7 +98,7 @@ module Unitwise
98
98
  # @return [Numeric] The equivalent magnitude on this scale
99
99
  # @api public
100
100
  def magnitude(scalar = scalar())
101
- terms.reduce(1.0) do |prod, term|
101
+ terms.reduce(1) do |prod, term|
102
102
  prod * term.magnitude(scalar)
103
103
  end
104
104
  end
@@ -1,3 +1,3 @@
1
1
  module Unitwise
2
- VERSION = '2.1.0'
2
+ VERSION = '2.2.0'.freeze
3
3
  end
@@ -86,32 +86,26 @@ module ScaleTests
86
86
  end
87
87
 
88
88
  describe "#simplified_value" do
89
- describe "when the value is equivalent to an Integer" do
90
- it "should convert from a Rational" do
91
- result = described_class.new(Rational(20,2), 'foot').simplified_value
92
- result.must_equal 10
93
- result.must_be_kind_of(Integer)
94
- end
95
- it "should convert from a Float" do
96
- result = described_class.new(4.0, 'foot').simplified_value
97
- result.must_equal 4
98
- result.must_be_kind_of(Integer)
99
- end
100
- it "should convert from a BigDecimal" do
101
- result = described_class.new(BigDecimal("4.5"), "volt").simplified_value
102
- result.must_equal 4.5
103
- result.must_be_kind_of(Float)
104
- end
89
+ it "must simplify to an Integer" do
90
+ result = described_class.new(4.0, 'foot').simplified_value
91
+ result.must_equal 4
92
+ result.must_be_kind_of(Integer)
105
93
  end
106
- describe "when the value is equivalent to a Float" do
107
- it "should convert from a BigDecimal" do
108
- result = described_class.new(BigDecimal("1.5"), 'foot').simplified_value
109
- result.must_equal 1.5
110
- result.must_be_kind_of(Float)
111
- end
94
+
95
+ it "must simplify to a Float" do
96
+ result = described_class.new(BigDecimal("1.5"), 'foot').simplified_value
97
+ result.must_equal 1.5
98
+ result.must_be_kind_of(Float)
112
99
  end
113
100
  end
114
101
 
102
+ describe "#inspect" do
103
+ it "must show the unit and value" do
104
+ result = described_class.new(12, 'meter').inspect
105
+ result.must_include("value=12")
106
+ result.must_include("unit=meter")
107
+ end
108
+ end
115
109
  end
116
110
  end
117
111
  end