flash_math 0.0.1
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 +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +17 -0
- data/.rspec +4 -0
- data/.travis.yml +13 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +187 -0
- data/Rakefile +6 -0
- data/flash_math.gemspec +27 -0
- data/lib/flash_math.rb +3 -0
- data/lib/flash_math/modules/geometry.rb +10 -0
- data/lib/flash_math/modules/geometry/geometric_bounding_box.rb +16 -0
- data/lib/flash_math/modules/geometry/geometric_distance.rb +20 -0
- data/lib/flash_math/modules/geometry/geometric_line.rb +87 -0
- data/lib/flash_math/modules/geometry/geometric_point.rb +19 -0
- data/lib/flash_math/modules/geometry/geometric_point_in_polygon.rb +63 -0
- data/lib/flash_math/modules/geometry/geometric_polygon.rb +36 -0
- data/lib/flash_math/modules/geometry/geometric_segment.rb +128 -0
- data/lib/flash_math/modules/geometry/geometric_vector.rb +46 -0
- data/lib/flash_math/modules/statistics.rb +1 -0
- data/lib/flash_math/modules/statistics/statistical_spread.rb +129 -0
- data/lib/flash_math/version.rb +3 -0
- data/spec/lib/geometry/geometric_bounding_box_spec.rb +67 -0
- data/spec/lib/geometry/geometric_distance_spec.rb +55 -0
- data/spec/lib/geometry/geometric_line_spec.rb +287 -0
- data/spec/lib/geometry/geometric_point_spec.rb +53 -0
- data/spec/lib/geometry/geometric_polygon_spec.rb +148 -0
- data/spec/lib/geometry/geometric_segment_spec.rb +231 -0
- data/spec/lib/geometry/geometric_vector_spec.rb +110 -0
- data/spec/lib/statistics/statistics_spread_spec.rb +219 -0
- data/spec/spec_helper.rb +4 -0
- metadata +168 -0
@@ -0,0 +1,231 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GeometricSegment do
|
4
|
+
|
5
|
+
describe '#initialize_by_points' do
|
6
|
+
point1 = GeometricPoint.new(1, 2)
|
7
|
+
point2 = GeometricPoint.new(3, 4)
|
8
|
+
segment = GeometricSegment.new(point1, point2)
|
9
|
+
|
10
|
+
it 'to be equal' do
|
11
|
+
expect(segment.point1).to eq(point1)
|
12
|
+
expect(segment.point2).to eq(point2)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'to be not equal' do
|
16
|
+
expect(segment.point1).not_to eq(point2)
|
17
|
+
expect(segment.point2).not_to eq(point1)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#initialize_by_arrays' do
|
22
|
+
point1 = GeometricPoint.new(1, 2)
|
23
|
+
point2 = GeometricPoint.new(3, 4)
|
24
|
+
segment = GeometricSegment.new_by_arrays([1, 2], [3, 4])
|
25
|
+
|
26
|
+
it 'to be equal' do
|
27
|
+
expect(segment.point1).to eq(point1)
|
28
|
+
expect(segment.point2).to eq(point2)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'to be not equal' do
|
32
|
+
expect(segment.point1).not_to eq(point2)
|
33
|
+
expect(segment.point2).not_to eq(point1)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#bounds' do
|
38
|
+
point1 = GeometricPoint.new(1, 1)
|
39
|
+
point2 = GeometricPoint.new(2, 2)
|
40
|
+
segment = GeometricSegment.new(point1, point2)
|
41
|
+
|
42
|
+
it 'to be the bottommost point' do
|
43
|
+
expect(segment.bottommost_endpoint).to eq(point1)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'to be the leftmost point' do
|
47
|
+
expect(segment.leftmost_endpoint).to eq(point1)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'to be the rightmost point' do
|
51
|
+
expect(segment.rightmost_endpoint).to eq(point2)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'to be the topmost point' do
|
55
|
+
expect(segment.topmost_endpoint).to eq(point2)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#contains_point?' do
|
60
|
+
it 'to be belongs to horizontal segment' do
|
61
|
+
expect(GeometricSegment.new_by_arrays([2, 1], [4, 1]).contains_point?(GeometricPoint.new(3, 1))).to eq(true)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'to be belongs to inclined segment' do
|
65
|
+
expect(GeometricSegment.new_by_arrays([2, 2], [4, 4]).contains_point?(GeometricPoint.new(3, 3))).to eq(true)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'to be is segment endpoint' do
|
69
|
+
expect(GeometricSegment.new_by_arrays([2, 1], [4, 1]).contains_point?(GeometricPoint.new(2, 1))).to eq(true)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'to be not belonging to segment' do
|
73
|
+
expect(GeometricSegment.new_by_arrays([2, 1], [4, 1]).contains_point?(GeometricPoint.new(2, 3))).to eq(false)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'to be on same horizontal line' do
|
77
|
+
expect(GeometricSegment.new_by_arrays([2, 1], [4, 1]).contains_point?(GeometricPoint.new(1, 1))).to eq(false)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'to be on same inclined line' do
|
81
|
+
expect(GeometricSegment.new_by_arrays([2, 2], [4, 4]).contains_point?(GeometricPoint.new(1, 1))).to eq(false)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe '#distance_to' do
|
86
|
+
it 'to be distance to point on segment' do
|
87
|
+
expect(GeometricSegment.new_by_arrays([0, 2], [2, 0]).distance_to(GeometricPoint.new(1, 1))).to eq(0)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'to be distance to flat segment' do
|
91
|
+
expect(GeometricSegment.new_by_arrays([0, 1], [2, 1]).distance_to(GeometricPoint.new(1, 2))).to eq(1)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'to be distance to segment start' do
|
95
|
+
expect(GeometricSegment.new_by_arrays([1, 1], [2, 1]).distance_to(GeometricPoint.new(0, 1))).to eq(1)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'to be distance to segment end' do
|
99
|
+
expect(GeometricSegment.new_by_arrays([0, 1], [0, 2]).distance_to(GeometricPoint.new(0, 3))).to eq(1)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '#intersection_point_with' do
|
104
|
+
it 'to be regular case' do
|
105
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [2, 2]).intersection_point_with(GeometricSegment.new_by_arrays([0, 2], [2, 0]))).to eq(GeometricPoint.new(1, 1))
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'to be intersected at the endpoint' do
|
109
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [2, 2]).intersection_point_with(GeometricSegment.new_by_arrays([0, 2], [2, 2]))).to eq(GeometricPoint.new(2, 2))
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe '#intersects_with?' do
|
114
|
+
it 'to be segments intersect' do
|
115
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [2, 0]).intersects_with?(GeometricSegment.new_by_arrays([1, 1], [1, -1]))).to eq(true)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'to be segments does not intersect but lay on intersecting lines' do
|
119
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [0, 2]).intersects_with?(GeometricSegment.new_by_arrays([1, 1], [3, 1]))).to eq(false)
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'to be segments does not intersect but line contains end point' do
|
123
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [0, 2]).intersects_with?(GeometricSegment.new_by_arrays([1, 0], [3, 0]))).to eq(false)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'to be segment contains endpoint' do
|
127
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [2, 2]).intersects_with?(GeometricSegment.new_by_arrays([0, 0], [2, 0]))).to eq(true)
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'to be segments parralel' do
|
131
|
+
expect(GeometricSegment.new_by_arrays([0, 1], [2, 1]).intersects_with?(GeometricSegment.new_by_arrays([0, 0], [2, 0]))).to eq(false)
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'to be segments parallel and have common endpoint' do
|
135
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [1, 0]).intersects_with?(GeometricSegment.new_by_arrays([1, 0], [2, 0]))).to eq(true)
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'to be segments overlap' do
|
139
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [2, 0]).intersects_with?(GeometricSegment.new_by_arrays([1, 0], [3, 0]))).to eq(true)
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'to be segments overlap on vertical line' do
|
143
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [0, 2]).intersects_with?(GeometricSegment.new_by_arrays([0, 1], [0, 3]))).to eq(true)
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'to be segments lie on one line' do
|
147
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [1, 0]).intersects_with?(GeometricSegment.new_by_arrays([2, 0], [3, 0]))).to eq(false)
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'to be segments lie on one vertical line' do
|
151
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [0, 1]).intersects_with?(GeometricSegment.new_by_arrays([0, 2], [0, 3]))).to eq(false)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe '#length' do
|
156
|
+
it 'to be parallel to axis' do
|
157
|
+
expect(GeometricSegment.new_by_arrays([1, 1], [1, 2]).length).to eq(1)
|
158
|
+
expect(GeometricSegment.new_by_arrays([1, 1], [2, 1]).length).to eq(1)
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'to be inclined' do
|
162
|
+
expect(GeometricSegment.new_by_arrays([1, 1], [2, 2]).length).to eq(Math.sqrt(2))
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe '#lies_on_one_line_with?' do
|
167
|
+
it 'to be parralel but on different lines' do
|
168
|
+
expect(GeometricSegment.new_by_arrays([0, 1], [2, 1]).lies_on_one_line_with?(GeometricSegment.new_by_arrays([0, 0], [2, 0]))).to eq(false)
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'to be not parralel' do
|
172
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [2, 0]).lies_on_one_line_with?(GeometricSegment.new_by_arrays([0, 1], [2, 2]))).to eq(false)
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'to be segment that lies on one horizontal line' do
|
176
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [1, 0]).lies_on_one_line_with?(GeometricSegment.new_by_arrays([2, 0], [3, 0]))).to eq(true)
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'to be segment that lies on one vertical line' do
|
180
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [0, 1]).lies_on_one_line_with?(GeometricSegment.new_by_arrays([0, 2], [0, 3]))).to eq(true)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe '#overlaps?' do
|
185
|
+
it 'to be overlaped' do
|
186
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [2, 0]).overlaps?(GeometricSegment.new_by_arrays([1, 0], [3, 0]))).to eq(true)
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'to be overlapes same segment' do
|
190
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [2, 0]).overlaps?(GeometricSegment.new_by_arrays([0, 0], [2, 0]))).to eq(true)
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'to be overlap intersects on one point' do
|
194
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [1, 0]).overlaps?(GeometricSegment.new_by_arrays([1, 0], [1, 1]))).to eq(false)
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'to be overlap lies on one horizontal line' do
|
198
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [2, 0]).overlaps?(GeometricSegment.new_by_arrays([4, 0], [6, 0]))).to eq(false)
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'to be overlap lies on one vertical line' do
|
202
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [0, 1]).overlaps?(GeometricSegment.new_by_arrays([0, 2], [0, 3]))).to eq(false)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe '#parallel_to?' do
|
207
|
+
it 'to be parallel' do
|
208
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [2, 1]).parallel_to?(GeometricSegment.new_by_arrays([1, 1], [5, 3]))).to eq(true)
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'to be not parallel' do
|
212
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [2, 1]).parallel_to?(GeometricSegment.new_by_arrays([1, 1], [2, 2]))).to eq(false)
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'to be lays on the same line' do
|
216
|
+
expect(GeometricSegment.new_by_arrays([0, 0], [1, 1]).parallel_to?(GeometricSegment.new_by_arrays([2, 2], [3, 3]))).to eq(true)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe '#to_vector' do
|
221
|
+
it 'to be parallel' do
|
222
|
+
expect(GeometricSegment.new_by_arrays([1, 1], [3, 2]).to_vector).to eq(GeometricVector.new(2, 1))
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'to be not parallel' do
|
226
|
+
expect(GeometricSegment.new_by_arrays([1, 1], [2, 2]).to_vector).to eq(GeometricVector.new(1, 1))
|
227
|
+
expect(GeometricSegment.new_by_arrays([2, 2], [1, 1]).to_vector).to eq(GeometricVector.new(-1, -1))
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GeometricVector do
|
4
|
+
describe '#initialize_by_numbers' do
|
5
|
+
vector = GeometricVector.new(1, 2)
|
6
|
+
|
7
|
+
it 'to be equal' do
|
8
|
+
expect(vector.x).to eq(1)
|
9
|
+
expect(vector.y).to eq(2)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'to be not equal' do
|
13
|
+
expect(vector.x).not_to eq(3)
|
14
|
+
expect(vector.y).not_to eq(3)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#initialize_by_array' do
|
19
|
+
vector = GeometricVector.new_by_array([1, 2])
|
20
|
+
|
21
|
+
it 'to be equal' do
|
22
|
+
expect(vector.x).to eq(1)
|
23
|
+
expect(vector.y).to eq(2)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'to be not equal' do
|
27
|
+
expect(vector.x).not_to eq(3)
|
28
|
+
expect(vector.y).not_to eq(3)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#+' do
|
33
|
+
it 'to be the addition of two vectors' do
|
34
|
+
expect(GeometricVector.new(1, 2) + GeometricVector.new(3, 4)).to eq(GeometricVector.new(4, 6))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#-' do
|
39
|
+
it 'to be subtraction of two vectors' do
|
40
|
+
expect(GeometricVector.new(1, 0) - GeometricVector.new(3, 4)).to eq(GeometricVector.new(-2, -4))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#*' do
|
45
|
+
it 'to be multipal of a point by scalar' do
|
46
|
+
expect(GeometricVector.new(1, 2) * -2).to eq(GeometricVector.new(-2, -4))
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'to be multipal of a point by vector' do
|
50
|
+
expect(-2 * GeometricVector.new(1, 2)).to eq(GeometricVector.new(-2, -4))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#collinear_with?' do
|
55
|
+
it 'to be collinear' do
|
56
|
+
expect(GeometricVector.new(1, 2).collinear_with?GeometricVector.new(2, 4)).to eq(true)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'to be not collinear' do
|
60
|
+
expect(GeometricVector.new(1, 2).collinear_with?GeometricVector.new(1, 1)).to eq(false)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'to be oppositely directed' do
|
64
|
+
expect(GeometricVector.new(2, 2).collinear_with?GeometricVector.new(-2, -2)).to eq(true)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#cross_product' do
|
69
|
+
it 'to be positive' do
|
70
|
+
expect(GeometricVector.new(1, 0).cross_product(GeometricVector.new(0, 1))).to eq(1)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'to be negative' do
|
74
|
+
expect(GeometricVector.new(0, 1).cross_product(GeometricVector.new(1, 0))).to eq(-1)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'to be zero' do
|
78
|
+
expect(GeometricVector.new(1, 1).cross_product(GeometricVector.new(-2, -2))).to eq(0)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'to be unnormalized' do
|
82
|
+
expect(GeometricVector.new(1, 1).cross_product(GeometricVector.new(-2, 2))).to eq(4)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#scalar_product' do
|
87
|
+
it 'to be perpendicular' do
|
88
|
+
expect(GeometricVector.new(1, 1).scalar_product(GeometricVector.new(-1, 1))).to eq(0)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'to be collinear' do
|
92
|
+
expect(GeometricVector.new(1, 1).scalar_product(GeometricVector.new(-2, -2))).to eq(-4)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'to be inclined' do
|
96
|
+
expect(GeometricVector.new(1, 1).scalar_product(GeometricVector.new(0, 1))).to eq(1)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#modulus' do
|
101
|
+
it 'to be parallel to axis' do
|
102
|
+
expect(GeometricVector.new(0, 1).modulus).to eq(1)
|
103
|
+
expect(GeometricVector.new(1, 0).modulus).to eq(1)
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'to be inclined' do
|
107
|
+
expect(GeometricVector.new(1, 1).modulus).to eq(1.4142135623730951)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,219 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe StatisticalSpread do
|
4
|
+
describe '#sum' do
|
5
|
+
it 'to be the sum of array values' do
|
6
|
+
expect(StatisticalSpread.new([1,2,6]).sum).to eq(9)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'to be a block passed' do
|
10
|
+
expect(StatisticalSpread.new([1,2,6]).sum{ |x| x * 2 }).to eq(18)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'to be 0 if empty' do
|
14
|
+
expect(StatisticalSpread.new([]).sum).to eq(0)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#mean" do
|
19
|
+
it "to be the sum of array values divided by number of array values" do
|
20
|
+
expect(StatisticalSpread.new([1,2,6]).mean).to eq(3)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "to be nil if empty" do
|
24
|
+
expect(StatisticalSpread.new([]).mean).to be_nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#median' do
|
29
|
+
it 'to be the value lying at the midpoint of the array' do
|
30
|
+
expect(StatisticalSpread.new([1,2,6]).median).to eq(2)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'to be the mean of the two midpoint values if the array length is even' do
|
34
|
+
expect(StatisticalSpread.new([1,2,3,6]).median).to eq(2.5)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'to be nil if empty' do
|
38
|
+
expect(StatisticalSpread.new([]).median).to be_nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#mode' do
|
43
|
+
it 'to be the most frequent value' do
|
44
|
+
expect(StatisticalSpread.new([1,1,2,46]).mode).to eq(1)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'to be the first value if there is only one' do
|
48
|
+
expect(StatisticalSpread.new([3.5]).mode).to eq(3.5)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'to be nil if nil if there is no most frequent value' do
|
52
|
+
expect(StatisticalSpread.new([1,2,3]).mode).to be_nil
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'to be nil if empty' do
|
56
|
+
expect(StatisticalSpread.new([]).mode).to be_nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#range' do
|
61
|
+
it 'to be the mean squared deviation of the sample (n - 1 denominator)' do
|
62
|
+
expect(StatisticalSpread.new([1,2,6]).range).to eq(5)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'to be nil if empty' do
|
66
|
+
expect(StatisticalSpread.new([]).range).to be_nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '#max' do
|
71
|
+
it 'to be the highest value' do
|
72
|
+
expect(StatisticalSpread.new([1,2,6]).max).to eq(6)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'to be nil if empty' do
|
76
|
+
expect(StatisticalSpread.new([]).max).to be_nil
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '#min' do
|
81
|
+
it 'to be the lowest value' do
|
82
|
+
expect(StatisticalSpread.new([1,2,6]).min).to eq(1)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'to be nil if empty' do
|
86
|
+
expect(StatisticalSpread.new([]).min).to be_nil
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe '#percentile_from_value' do
|
91
|
+
it 'to be the precise percentile of each value' do
|
92
|
+
data = [95.1772, 95.1567, 95.1937, 95.1959, 95.1442, 95.061, 95.1591, 95.1195,95.1065, 95.0925, 95.199, 95.1682]
|
93
|
+
percentiles = [0,9,17,25,34,42,50,59,67,75,84,92]
|
94
|
+
stats = StatisticalSpread.new(data)
|
95
|
+
data.sort.each_with_index do |datum, i|
|
96
|
+
expect(stats.percentile_from_value(datum)).to eq(percentiles[i])
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'to be nil if empty' do
|
101
|
+
expect(StatisticalSpread.new([]).percentile_from_value(1)).to be_nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe '#value_from_percentile' do
|
106
|
+
it 'to be the precise percentile of each value' do
|
107
|
+
data = [95.1772, 95.1567, 95.1937, 95.1959, 95.1442, 95.061, 95.1591, 95.1195,95.1065, 95.0925, 95.199, 95.1682]
|
108
|
+
percentiles = [0,10,20,30,40,50,60,70,80,90]
|
109
|
+
values = [95.061,95.1065,95.1195,95.1442,95.1567,95.1591,95.1772,95.1937,95.1959,95.199]
|
110
|
+
stats = StatisticalSpread.new(data)
|
111
|
+
percentiles.sort.each_with_index do |percentile, i|
|
112
|
+
expect(stats.value_from_percentile(percentile)).to eq(values[i])
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'to be nil if empty' do
|
117
|
+
expect(StatisticalSpread.new([]).value_from_percentile(1)).to be_nil
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe '#variance' do
|
122
|
+
it 'to be the mean squared deviation of the sample (n - 1 denominator)' do
|
123
|
+
expect(StatisticalSpread.new([1,2,6]).variance).to eq(7)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'to be nil if empty' do
|
127
|
+
expect(StatisticalSpread.new([]).variance).to be_nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe '#population_variance' do
|
132
|
+
it 'to be the mean squared deviation of the sample' do
|
133
|
+
expect(StatisticalSpread.new([1,2,3,4]).population_variance).to eq(1.25)
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'to be nil if empty' do
|
137
|
+
expect(StatisticalSpread.new([]).population_variance).to be_nil
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe '#standard_deviation' do
|
142
|
+
it 'to be the square root of the #variance' do
|
143
|
+
expect(StatisticalSpread.new([1,2,6]).standard_deviation).to eq(2.6457513110645907)
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'to be nil for single element arrays' do
|
147
|
+
expect(StatisticalSpread.new([1]).standard_deviation).to be_nil
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'to be nil if empty' do
|
151
|
+
expect(StatisticalSpread.new([]).standard_deviation).to be_nil
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe '#relative_standard_deviation' do
|
156
|
+
it 'to be 0 for constant values' do
|
157
|
+
expect(StatisticalSpread.new([100,100,100]).relative_standard_deviation).to eq(0)
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'to be the #population_standard_deviation divided by the mean * 100' do
|
161
|
+
expect(StatisticalSpread.new([90,100,110]).relative_standard_deviation).to be_within(0.01).of(8.16)
|
162
|
+
expect(StatisticalSpread.new([1,5,6,8,10,40,65,88]).relative_standard_deviation).to be_within(0.01).of(110.41)
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'to be nil if empty' do
|
166
|
+
expect(StatisticalSpread.new([]).relative_standard_deviation).to be_nil
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe '#population_standard_deviation' do
|
171
|
+
it 'to be the square root of the #population_variance' do
|
172
|
+
expect(StatisticalSpread.new([1,2,6]).population_standard_deviation).to eq(2.160246899469287)
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'to be 0 for single element arrays' do
|
176
|
+
expect(StatisticalSpread.new([1]).population_standard_deviation).to eq(0)
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'to be nil if empty' do
|
180
|
+
expect(StatisticalSpread.new([]).population_standard_deviation).to be_nil
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe '#skewness' do
|
185
|
+
it 'to be the measure of skewness of the data as close to 0 when not skewed' do
|
186
|
+
expect(StatisticalSpread.new([1,3,5,3,1]).skewness).to eq(0.30734449954312965)
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'to be the measure of skewness of the data as high when skewed' do
|
190
|
+
expect(StatisticalSpread.new([50,10,1,1,1]).skewness).to eq(1.2374536958450908)
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'to be 0 if only one element' do
|
194
|
+
expect(StatisticalSpread.new([1]).skewness).to eq(0)
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'to be nil if empty' do
|
198
|
+
expect(StatisticalSpread.new([]).skewness).to be_nil
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
describe '#kurtosis' do
|
203
|
+
it 'to be the measure of kurtosis of the data as close to 0 when not skewed' do
|
204
|
+
expect(StatisticalSpread.new([1,3,5,3,1]).kurtosis).to eq(1.477551020408163)
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'to be the measure of skewness of the data as high when skewed' do
|
208
|
+
expect(StatisticalSpread.new([99,10,1,1,1]).kurtosis).to eq(2.56586117539186)
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'to be 0 if only one element' do
|
212
|
+
expect(StatisticalSpread.new([1]).kurtosis).to eq(0)
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'to be nil if empty' do
|
216
|
+
expect(StatisticalSpread.new([]).kurtosis).to be_nil
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|