greater_less 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/.travis.yml +1 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +45 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +103 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/lib/greater_less.rb +244 -0
- data/lib/greater_less/string_extension.rb +10 -0
- data/spec/greater_less_spec.rb +284 -0
- data/spec/spec_helper.rb +32 -0
- metadata +161 -0
data/.document
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
language: ruby
|
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development, :test do
|
9
|
+
gem 'rspec'
|
10
|
+
gem 'shoulda'
|
11
|
+
gem 'rdoc'
|
12
|
+
gem 'bundler'
|
13
|
+
gem 'jeweler'
|
14
|
+
gem "spork"
|
15
|
+
end
|
16
|
+
|
17
|
+
gem 'simplecov', :require => false, :group => :test
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
diff-lcs (1.1.3)
|
5
|
+
git (1.2.5)
|
6
|
+
jeweler (1.8.3)
|
7
|
+
bundler (~> 1.0)
|
8
|
+
git (>= 1.2.5)
|
9
|
+
rake
|
10
|
+
rdoc
|
11
|
+
json (1.6.5)
|
12
|
+
multi_json (1.2.0)
|
13
|
+
rake (0.9.2.2)
|
14
|
+
rdoc (3.12)
|
15
|
+
json (~> 1.4)
|
16
|
+
rspec (2.8.0)
|
17
|
+
rspec-core (~> 2.8.0)
|
18
|
+
rspec-expectations (~> 2.8.0)
|
19
|
+
rspec-mocks (~> 2.8.0)
|
20
|
+
rspec-core (2.8.0)
|
21
|
+
rspec-expectations (2.8.0)
|
22
|
+
diff-lcs (~> 1.1.2)
|
23
|
+
rspec-mocks (2.8.0)
|
24
|
+
shoulda (3.0.1)
|
25
|
+
shoulda-context (~> 1.0.0)
|
26
|
+
shoulda-matchers (~> 1.0.0)
|
27
|
+
shoulda-context (1.0.0)
|
28
|
+
shoulda-matchers (1.0.0)
|
29
|
+
simplecov (0.6.1)
|
30
|
+
multi_json (~> 1.0)
|
31
|
+
simplecov-html (~> 0.5.3)
|
32
|
+
simplecov-html (0.5.3)
|
33
|
+
spork (0.8.5)
|
34
|
+
|
35
|
+
PLATFORMS
|
36
|
+
ruby
|
37
|
+
|
38
|
+
DEPENDENCIES
|
39
|
+
bundler
|
40
|
+
jeweler
|
41
|
+
rdoc
|
42
|
+
rspec
|
43
|
+
shoulda
|
44
|
+
simplecov
|
45
|
+
spork
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Samuel Esposito
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
= greater_less
|
2
|
+
|
3
|
+
The GreaterLess class can be used to generate objects that represent
|
4
|
+
halfopen intervals, but transparently behave as Floats. One easy way to
|
5
|
+
integrate this class into your project is by requiring the greater_less
|
6
|
+
string extension as follows:
|
7
|
+
|
8
|
+
require 'greater_less/string_extension'
|
9
|
+
|
10
|
+
This extension redifines the +#to_f+ method of the String class as follows:
|
11
|
+
|
12
|
+
class String
|
13
|
+
alias :to_f_without_greater_less :to_f
|
14
|
+
|
15
|
+
def to_f
|
16
|
+
if self =~ GreaterLess::GREATER_LESS
|
17
|
+
return GreaterLess.new(self)
|
18
|
+
end
|
19
|
+
self.to_f_without_greater_less
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Now when a string starts with a greater or less sign (like for instance
|
24
|
+
<tt>"> 3.45"</tt>), the +#to_f+ method converts it to a GreaterLess object
|
25
|
+
instead of the value +0.0+.
|
26
|
+
|
27
|
+
With this extension in place one can simply convert strings like the one
|
28
|
+
above to a float like object and compare it to floats as if it were a
|
29
|
+
float itself. For instance one can do the following:
|
30
|
+
|
31
|
+
>> value = ">3.45".to_f
|
32
|
+
=> > 3.45
|
33
|
+
>> value > 2.45
|
34
|
+
=> true
|
35
|
+
>> value >= 2.45
|
36
|
+
=> true
|
37
|
+
>> 2.45 > value
|
38
|
+
=> false
|
39
|
+
>> 2.45 >= value
|
40
|
+
=> false
|
41
|
+
>> value == ">3.45".to_f
|
42
|
+
=> true
|
43
|
+
>> value != 2.45
|
44
|
+
=> true
|
45
|
+
|
46
|
+
It is also possible to compare GreaterLess values with each other, so you
|
47
|
+
do not have to worry about what kind of object you are dealing with in your
|
48
|
+
code:
|
49
|
+
|
50
|
+
>> value1 = ">3.45".to_f
|
51
|
+
=> > 3.45
|
52
|
+
>> value2 = "< 2.45".to_f
|
53
|
+
=> < 2.45
|
54
|
+
>> value1 > value2
|
55
|
+
=> true
|
56
|
+
>> value2 > value1
|
57
|
+
=> false
|
58
|
+
|
59
|
+
Finally it is possible to apply simple arithmetics to GreaterLess objects
|
60
|
+
like addition, subtraction, multiplication and division:
|
61
|
+
|
62
|
+
>> value = ">3.45".to_f
|
63
|
+
=> > 3.45
|
64
|
+
>> value + 2
|
65
|
+
=> > 5.45
|
66
|
+
>> value - 2
|
67
|
+
=> > 1.4500000000000002
|
68
|
+
>> value * 2
|
69
|
+
=> > 1.725
|
70
|
+
|
71
|
+
Inverting the object's sign when multiplying with a negative numerical
|
72
|
+
or using a GreaterLess object in the denominator is nicely dealt with:
|
73
|
+
|
74
|
+
>> value = ">3.45".to_f
|
75
|
+
=> > 3.45
|
76
|
+
>> -1 * value
|
77
|
+
=> < -3.45
|
78
|
+
>> 1 / value
|
79
|
+
=> < 0.2898550724637681
|
80
|
+
>> -1 / value
|
81
|
+
=> > -0.2898550724637681
|
82
|
+
|
83
|
+
It makes no sense to apply the operators +, -, * or / on a pair of GreaterLess
|
84
|
+
objects, so an exception is raised in these cases.
|
85
|
+
|
86
|
+
All other methods are simply passed to the float value the GreaterLess
|
87
|
+
object contains, so that it transparently acts like a float.
|
88
|
+
|
89
|
+
== Contributing to greater_less
|
90
|
+
|
91
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
92
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
93
|
+
* Fork the project.
|
94
|
+
* Start a feature/bugfix branch.
|
95
|
+
* Commit and push until you are happy with your contribution.
|
96
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
97
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
98
|
+
|
99
|
+
== Copyright
|
100
|
+
|
101
|
+
Copyright (c) 2012 Samuel Esposito. See LICENSE.txt for
|
102
|
+
further details.
|
103
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler'
|
4
|
+
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "greater_less"
|
18
|
+
gem.homepage = "http://github.com/esposito/greater_less"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Gem for handling floating point half-open intervals}
|
21
|
+
gem.description = %Q{The GreaterLess Gem allows for making comparisons between floats and half-open intervals and apply simple arithmetics to the intervals preserving their mathematical meaning.}
|
22
|
+
gem.email = "s.esposito@roqua.nl"
|
23
|
+
gem.authors = ["Samuel Esposito"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rspec/core'
|
29
|
+
require 'rspec/core/rake_task'
|
30
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
31
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
32
|
+
end
|
33
|
+
|
34
|
+
# RSpec::Core::RakeTask.new(:rcov) do |spec|
|
35
|
+
# spec.pattern = 'spec/**/*_spec.rb'
|
36
|
+
# spec.rcov = true
|
37
|
+
# end
|
38
|
+
|
39
|
+
task :default => :spec
|
40
|
+
|
41
|
+
require 'rdoc/task'
|
42
|
+
Rake::RDocTask.new do |rdoc|
|
43
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
44
|
+
|
45
|
+
rdoc.rdoc_dir = 'rdoc'
|
46
|
+
rdoc.title = "greater_less #{version}"
|
47
|
+
rdoc.rdoc_files.include('README*')
|
48
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
49
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/greater_less.rb
ADDED
@@ -0,0 +1,244 @@
|
|
1
|
+
# The GreaterLess class can be used to generate objects that represent
|
2
|
+
# halfopen intervals, but transparently behave as Floats. One easy way to
|
3
|
+
# integrate this class into your project is by requiring the greater_less
|
4
|
+
# string extension as follows:
|
5
|
+
#
|
6
|
+
# require 'greater_less/string_extension'
|
7
|
+
#
|
8
|
+
# This extension redifines the +#to_f+ method of the String class as follows:
|
9
|
+
#
|
10
|
+
# class String
|
11
|
+
# alias :to_f_without_greater_less :to_f
|
12
|
+
#
|
13
|
+
# def to_f
|
14
|
+
# if self =~ GreaterLess::GREATER_LESS
|
15
|
+
# return GreaterLess.new(self)
|
16
|
+
# end
|
17
|
+
# self.to_f_without_greater_less
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# Now when a string starts with a greater or less sign (like for instance
|
22
|
+
# <tt>"> 3.45"</tt>), the +#to_f+ method converts it to a GreaterLess object
|
23
|
+
# instead of the value +0.0+.
|
24
|
+
#
|
25
|
+
# With this extension in place one can simply convert strings like the one
|
26
|
+
# above to a float like object and compare it to floats as if it were a
|
27
|
+
# float itself. For instance one can do the following:
|
28
|
+
#
|
29
|
+
# >> value = ">3.45".to_f
|
30
|
+
# => > 3.45
|
31
|
+
# >> value > 2.45
|
32
|
+
# => true
|
33
|
+
# >> value >= 2.45
|
34
|
+
# => true
|
35
|
+
# >> 2.45 > value
|
36
|
+
# => false
|
37
|
+
# >> 2.45 >= value
|
38
|
+
# => false
|
39
|
+
# >> value == ">3.45".to_f
|
40
|
+
# => true
|
41
|
+
# >> value != 2.45
|
42
|
+
# => true
|
43
|
+
#
|
44
|
+
# It is also possible to compare GreaterLess values with each other, so you
|
45
|
+
# do not have to worry about what kind of object you are dealing with in your
|
46
|
+
# code:
|
47
|
+
#
|
48
|
+
# >> value1 = ">3.45".to_f
|
49
|
+
# => > 3.45
|
50
|
+
# >> value2 = "< 2.45".to_f
|
51
|
+
# => < 2.45
|
52
|
+
# >> value1 > value2
|
53
|
+
# => true
|
54
|
+
# >> value2 > value1
|
55
|
+
# => false
|
56
|
+
#
|
57
|
+
# Finally it is possible to apply simple arithmetics to GreaterLess objects
|
58
|
+
# like addition, subtraction, multiplication and division:
|
59
|
+
#
|
60
|
+
# >> value = ">3.45".to_f
|
61
|
+
# => > 3.45
|
62
|
+
# >> value + 2
|
63
|
+
# => > 5.45
|
64
|
+
# >> value - 2
|
65
|
+
# => > 1.4500000000000002
|
66
|
+
# >> value * 2
|
67
|
+
# => > 1.725
|
68
|
+
#
|
69
|
+
# Inverting the object's sign when multiplying with a negative numerical
|
70
|
+
# or using a GreaterLess object in the denominator is nicely dealt with:
|
71
|
+
#
|
72
|
+
# >> value = ">3.45".to_f
|
73
|
+
# => > 3.45
|
74
|
+
# >> -1 * value
|
75
|
+
# => < -3.45
|
76
|
+
# >> 1 / value
|
77
|
+
# => < 0.2898550724637681
|
78
|
+
# >> -1 / value
|
79
|
+
# => > -0.2898550724637681
|
80
|
+
#
|
81
|
+
# It makes no sense to apply the operators +, -, * or / on a pair of GreaterLess
|
82
|
+
# objects, so an exception is raised in these cases.
|
83
|
+
#
|
84
|
+
# All other methods are simply passed to the float value the GreaterLess
|
85
|
+
# object contains, so that it transparently acts like a float.
|
86
|
+
#
|
87
|
+
|
88
|
+
class GreaterLess
|
89
|
+
instance_methods.each do |meth|
|
90
|
+
# skipping undef of methods that "may cause serious problems"
|
91
|
+
undef_method(meth) if meth !~ /^(__|object_id|class)/
|
92
|
+
end
|
93
|
+
|
94
|
+
GREATER_LESS = /^[<>] ?/
|
95
|
+
|
96
|
+
#:nodoc:
|
97
|
+
class << self
|
98
|
+
alias :old_new :new
|
99
|
+
|
100
|
+
def new(content, coerce=false)
|
101
|
+
if coerce or content =~ GREATER_LESS
|
102
|
+
old_new(content)
|
103
|
+
else
|
104
|
+
content.to_f
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def initialize(content)
|
110
|
+
if content.is_a? String
|
111
|
+
if content =~ /^>/
|
112
|
+
@sign = ">"
|
113
|
+
elsif content =~ /^</
|
114
|
+
@sign = "<"
|
115
|
+
end
|
116
|
+
@float = content.gsub(/^[<>] ?/, "").to_f
|
117
|
+
elsif content.is_a? Numeric
|
118
|
+
@float = content.to_f
|
119
|
+
else
|
120
|
+
raise "Can't handle #{content.class}!"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def coerce(object)
|
125
|
+
if object.is_a? Numeric and not object.is_a? self.class
|
126
|
+
[GreaterLess.new(object, true), self]
|
127
|
+
else
|
128
|
+
raise "Can't handle #{object.class}!"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def sign
|
133
|
+
@sign
|
134
|
+
end
|
135
|
+
|
136
|
+
def inverted_sign
|
137
|
+
case @sign
|
138
|
+
when ">"
|
139
|
+
"<"
|
140
|
+
when "<"
|
141
|
+
">"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def value
|
146
|
+
@float
|
147
|
+
end
|
148
|
+
|
149
|
+
#:doc:
|
150
|
+
def ==(numerical)
|
151
|
+
if numerical.is_a? self.class
|
152
|
+
@sign == numerical.sign and @float == numerical.value
|
153
|
+
else
|
154
|
+
false
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def >(numerical)
|
159
|
+
if numerical.is_a? self.class
|
160
|
+
@float >= numerical.value and [nil, ">"].include? @sign and [nil, "<"].include? numerical.sign
|
161
|
+
else
|
162
|
+
@float >= numerical and @sign == ">"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def <(numerical)
|
167
|
+
numerical > self
|
168
|
+
end
|
169
|
+
|
170
|
+
def !=(numerical)
|
171
|
+
not self == numerical
|
172
|
+
end
|
173
|
+
|
174
|
+
def >=(numerical)
|
175
|
+
self == numerical or self > numerical
|
176
|
+
end
|
177
|
+
|
178
|
+
def <=(numerical)
|
179
|
+
self == numerical or self < numerical
|
180
|
+
end
|
181
|
+
|
182
|
+
def *(numerical)
|
183
|
+
value, sign = if numerical.is_a? self.class
|
184
|
+
raise "Can't handle #{self.class}!" if @sign
|
185
|
+
[@float * numerical.value, @float > 0 ? numerical.sign : numerical.inverted_sign]
|
186
|
+
else
|
187
|
+
[@float * numerical, numerical > 0 ? @sign : inverted_sign]
|
188
|
+
end
|
189
|
+
GreaterLess.new("#{sign} #{value}")
|
190
|
+
end
|
191
|
+
|
192
|
+
def /(numerical)
|
193
|
+
value, sign = if numerical.is_a? self.class
|
194
|
+
raise "Can't handle #{self.class}!" if @sign
|
195
|
+
[@float / numerical.value, @float > 0 ? numerical.inverted_sign : numerical.sign]
|
196
|
+
else
|
197
|
+
[@float / numerical, numerical > 0 ? @sign : inverted_sign]
|
198
|
+
end
|
199
|
+
GreaterLess.new("#{sign} #{value}")
|
200
|
+
end
|
201
|
+
|
202
|
+
def +(numerical)
|
203
|
+
value, sign = if numerical.is_a? self.class
|
204
|
+
raise "Can't handle #{self.class}!" if @sign
|
205
|
+
[@float + numerical.value, numerical.sign]
|
206
|
+
else
|
207
|
+
[@float + numerical, @sign]
|
208
|
+
end
|
209
|
+
GreaterLess.new("#{sign} #{value}")
|
210
|
+
end
|
211
|
+
|
212
|
+
def -(numerical)
|
213
|
+
self + -numerical
|
214
|
+
end
|
215
|
+
|
216
|
+
def -@
|
217
|
+
GreaterLess.new("#{inverted_sign} -#{value}")
|
218
|
+
end
|
219
|
+
|
220
|
+
#:nodoc:
|
221
|
+
def to_f
|
222
|
+
self
|
223
|
+
end
|
224
|
+
|
225
|
+
def to_s
|
226
|
+
"#{@sign} #{@float}"
|
227
|
+
end
|
228
|
+
|
229
|
+
def inspect
|
230
|
+
self.to_s
|
231
|
+
end
|
232
|
+
|
233
|
+
def is_a?(klass)
|
234
|
+
if klass == self.class
|
235
|
+
true
|
236
|
+
else
|
237
|
+
@float.is_a? klass
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def method_missing(*args)
|
242
|
+
@float.send(*args)
|
243
|
+
end
|
244
|
+
end
|
@@ -0,0 +1,284 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GreaterLess do
|
4
|
+
|
5
|
+
context "when the object is initialized with a string" do
|
6
|
+
context "and the string starts with a greater than sign" do
|
7
|
+
subject { GreaterLess.new("> 4.5") }
|
8
|
+
|
9
|
+
it "should differ from its float value" do
|
10
|
+
(subject == 4.5).should be_false
|
11
|
+
(subject != 4.5).should be_true
|
12
|
+
(4.5 == subject).should be_false
|
13
|
+
(4.5 != subject).should be_true
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should be greater than its float value" do
|
17
|
+
(subject > 4.5).should be_true
|
18
|
+
(subject >= 4.5).should be_true
|
19
|
+
(4.5 < subject).should be_true
|
20
|
+
(4.5 <= subject).should be_true
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should be greater than any value that is less than its float value" do
|
24
|
+
(subject > 4.49).should be_true
|
25
|
+
(subject >= 4.49).should be_true
|
26
|
+
(4.49 < subject).should be_true
|
27
|
+
(4.49 <= subject).should be_true
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should not be greater than a value greater than its float value" do
|
31
|
+
(subject > 4.51).should be_false
|
32
|
+
(subject >= 4.51).should be_false
|
33
|
+
(4.51 < subject).should be_false
|
34
|
+
(4.51 <= subject).should be_false
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should not be less than a value that is greater than its float value" do
|
38
|
+
(subject < 4.51).should be_false
|
39
|
+
(subject <= 4.51).should be_false
|
40
|
+
(4.51 > subject).should be_false
|
41
|
+
(4.51 >= subject).should be_false
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should be greater than a GreaterLess object that has a smaller or equal value and a less sign" do
|
45
|
+
(subject > GreaterLess.new("< 4.49")).should be_true
|
46
|
+
(subject > GreaterLess.new("< 4.5") ).should be_true
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should not be greater than a GreaterLess object that has a bigger value or a greater sign" do
|
50
|
+
(subject > GreaterLess.new("< 4.51")).should be_false
|
51
|
+
(subject > GreaterLess.new("> 4.49")).should be_false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "and the string starts with a less than sign" do
|
56
|
+
subject { GreaterLess.new("<4.5") }
|
57
|
+
|
58
|
+
it "should differ from its float value" do
|
59
|
+
(subject == 4.5).should be_false
|
60
|
+
(subject != 4.5).should be_true
|
61
|
+
(4.5 == subject).should be_false
|
62
|
+
(4.5 != subject).should be_true
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should be less than its float value" do
|
66
|
+
(subject < 4.5).should be_true
|
67
|
+
(subject <= 4.5).should be_true
|
68
|
+
(4.5 > subject).should be_true
|
69
|
+
(4.5 >= subject).should be_true
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should be less than any value that is greater than its float value" do
|
73
|
+
(subject < 4.51).should be_true
|
74
|
+
(subject <= 4.51).should be_true
|
75
|
+
(4.51 > subject).should be_true
|
76
|
+
(4.51 >= subject).should be_true
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should not be less than a value less than its float value" do
|
80
|
+
(subject < 4.49).should be_false
|
81
|
+
(subject <= 4.49).should be_false
|
82
|
+
(4.49 > subject).should be_false
|
83
|
+
(4.49 >= subject).should be_false
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should not be greater than a value that is less than its float value" do
|
87
|
+
(subject > 4.49).should be_false
|
88
|
+
(subject >= 4.49).should be_false
|
89
|
+
(4.49 < subject).should be_false
|
90
|
+
(4.49 <= subject).should be_false
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context "and the string contains no sign" do
|
95
|
+
subject { GreaterLess.new("4.5") }
|
96
|
+
|
97
|
+
it "should be a float" do
|
98
|
+
subject.class.should == Float
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe ".initialize" do
|
104
|
+
context "when it receives something different from a string or a numeric" do
|
105
|
+
it "should raise an exception" do
|
106
|
+
expect { GreaterLess.new(Object.new, true) }.to raise_error
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context "when the object is initialized with a string containing a sign" do
|
112
|
+
subject { GreaterLess.new(">4.5") }
|
113
|
+
|
114
|
+
it "should be a float" do
|
115
|
+
subject.should be_a(Float)
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should equal itself" do
|
119
|
+
(subject == subject).should be_true
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "#coerce" do
|
123
|
+
it "should raise an exception if it is called on a GreaterLess object" do
|
124
|
+
expect { subject.coerce(GreaterLess.new("<2.45")) }.to raise_error
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "#inverted_sign" do
|
129
|
+
it "should return a less sign when the object's sign is a greater sign" do
|
130
|
+
GreaterLess.new("> 1").inverted_sign.should eq("<")
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should return a greater sign when the object's sign is a less sign" do
|
134
|
+
GreaterLess.new("< 1").inverted_sign.should eq(">")
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "#*" do
|
139
|
+
it "should return a GreaterLess object" do
|
140
|
+
(subject * 4).class.should == GreaterLess
|
141
|
+
(4 * subject).class.should == GreaterLess
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should carry out multiplication on its float value" do
|
145
|
+
(subject * 4).value.should == 18
|
146
|
+
(4 * subject).value.should == 18
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should retain the object's sign when the argument is a positive numeric" do
|
150
|
+
(subject * 4).sign.should == subject.sign
|
151
|
+
(4 * subject).sign.should == subject.sign
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should invert the object's sign when the argument is a negative numeric" do
|
155
|
+
(subject * -4).sign.should == subject.inverted_sign
|
156
|
+
(-4 * subject).sign.should == subject.inverted_sign
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should raise an exception when the argument is a GreaterLess object" do
|
160
|
+
expect { subject * GreaterLess.new("<1.2") }.to raise_error
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe "#/" do
|
165
|
+
it "should return a GreaterLess object" do
|
166
|
+
(subject / 4).class.should == GreaterLess
|
167
|
+
(4 / subject).class.should == GreaterLess
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should carry out division on its float value" do
|
171
|
+
(subject / 4).value.should == 4.5 / 4
|
172
|
+
(4 / subject).value.should == 4 / 4.5
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should retain the object's sign when the denominator is a positive numeric" do
|
176
|
+
(subject / 4).sign.should == subject.sign
|
177
|
+
end
|
178
|
+
|
179
|
+
it "should retain the object's sign when the numerator is a negative numeric" do
|
180
|
+
(-4 / subject).sign.should == subject.sign
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should invert the object's sign when the object itself is the denominator" do
|
184
|
+
(4 / subject).sign.should == subject.inverted_sign
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should invert the object's sign when the denominator is a negative numeric" do
|
188
|
+
(subject / -4).sign.should == subject.inverted_sign
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should raise an exception when the argument is a GreaterLess object" do
|
192
|
+
expect { subject / GreaterLess.new("<1.2") }.to raise_error
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe "#+" do
|
197
|
+
it "should return a GreaterLess object" do
|
198
|
+
(subject + 4).class.should == GreaterLess
|
199
|
+
(4 + subject).class.should == GreaterLess
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should carry out addition on its float value" do
|
203
|
+
(subject + 4).value.should == 8.5
|
204
|
+
(4 + subject).value.should == 8.5
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should retain the object's sign" do
|
208
|
+
(subject + 4).sign.should == subject.sign
|
209
|
+
(4 + subject).sign.should == subject.sign
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should raise an exception when the argument is a GreaterLess object" do
|
213
|
+
expect { subject + GreaterLess.new("<1.2") }.to raise_error
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe "#-" do
|
218
|
+
it "should return a GreaterLess object" do
|
219
|
+
(subject - 4).class.should == GreaterLess
|
220
|
+
(4 - subject).class.should == GreaterLess
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should carry out subtraction on its float value" do
|
224
|
+
(subject - 4).value.should == 0.5
|
225
|
+
(4 - subject).value.should == -0.5
|
226
|
+
end
|
227
|
+
|
228
|
+
it "should retain the object's sign when a numerical is subtracted from it" do
|
229
|
+
(subject - 4).sign.should == subject.sign
|
230
|
+
end
|
231
|
+
|
232
|
+
it "should invert the object's sign when it is subtracted form a numerical" do
|
233
|
+
(4 - subject).sign.should == subject.inverted_sign
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should raise an exception when the argument is a GreaterLess object" do
|
237
|
+
expect { subject - GreaterLess.new("<1.2") }.to raise_error
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
describe "#-@" do
|
242
|
+
it "should return a GreaterLess object" do
|
243
|
+
(-subject).class.should == GreaterLess
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should negate the object's value" do
|
247
|
+
(-subject).value.should == -subject.value
|
248
|
+
end
|
249
|
+
|
250
|
+
it "should invert the object's sign" do
|
251
|
+
(-subject).sign.should == subject.inverted_sign
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
describe "#to_f" do
|
256
|
+
it "should return the object itself" do
|
257
|
+
subject.to_f.class.should == GreaterLess
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
describe "#to_s" do
|
262
|
+
it "should include this sign" do
|
263
|
+
subject.to_s.should == "> 4.5"
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
describe "#inspect" do
|
268
|
+
it "should include this sign" do
|
269
|
+
subject.inspect.should == "> 4.5"
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
describe "#is_a?" do
|
274
|
+
it "should acknowledge the GreaterLess class" do
|
275
|
+
subject.is_a?(GreaterLess).should be_true
|
276
|
+
end
|
277
|
+
|
278
|
+
it "should acknowledge the Float class" do
|
279
|
+
subject.is_a?(Float).should be_true
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
if ENV['COVERAGE']
|
3
|
+
require 'simplecov'
|
4
|
+
SimpleCov.start
|
5
|
+
end
|
6
|
+
|
7
|
+
# --- Instructions ---
|
8
|
+
# - Sort through your spec_helper file. Place as much environment loading
|
9
|
+
# code that you don't normally modify during development in the
|
10
|
+
# Spork.prefork block.
|
11
|
+
# - Place the rest under Spork.each_run block
|
12
|
+
# - Any code that is left outside of the blocks will be ran during preforking
|
13
|
+
# and during each_run!
|
14
|
+
# - These instructions should self-destruct in 10 seconds. If they don't,
|
15
|
+
# feel free to delete them.
|
16
|
+
#
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
22
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
23
|
+
require 'rspec'
|
24
|
+
require 'greater_less'
|
25
|
+
|
26
|
+
# Requires supporting files with custom matchers and macros, etc,
|
27
|
+
# in ./support/ and its subdirectories.
|
28
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
29
|
+
|
30
|
+
RSpec.configure do |config|
|
31
|
+
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: greater_less
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Samuel Esposito
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: shoulda
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rdoc
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: bundler
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: jeweler
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: spork
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
description: The GreaterLess Gem allows for making comparisons between floats and
|
111
|
+
half-open intervals and apply simple arithmetics to the intervals preserving their
|
112
|
+
mathematical meaning.
|
113
|
+
email: s.esposito@roqua.nl
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files:
|
117
|
+
- LICENSE.txt
|
118
|
+
- README.rdoc
|
119
|
+
files:
|
120
|
+
- .document
|
121
|
+
- .rspec
|
122
|
+
- .travis.yml
|
123
|
+
- Gemfile
|
124
|
+
- Gemfile.lock
|
125
|
+
- LICENSE.txt
|
126
|
+
- README.rdoc
|
127
|
+
- Rakefile
|
128
|
+
- VERSION
|
129
|
+
- lib/greater_less.rb
|
130
|
+
- lib/greater_less/string_extension.rb
|
131
|
+
- spec/greater_less_spec.rb
|
132
|
+
- spec/spec_helper.rb
|
133
|
+
homepage: http://github.com/esposito/greater_less
|
134
|
+
licenses:
|
135
|
+
- MIT
|
136
|
+
post_install_message:
|
137
|
+
rdoc_options: []
|
138
|
+
require_paths:
|
139
|
+
- lib
|
140
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
141
|
+
none: false
|
142
|
+
requirements:
|
143
|
+
- - ! '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
segments:
|
147
|
+
- 0
|
148
|
+
hash: -1315675163151725512
|
149
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
150
|
+
none: false
|
151
|
+
requirements:
|
152
|
+
- - ! '>='
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0'
|
155
|
+
requirements: []
|
156
|
+
rubyforge_project:
|
157
|
+
rubygems_version: 1.8.21
|
158
|
+
signing_key:
|
159
|
+
specification_version: 3
|
160
|
+
summary: Gem for handling floating point half-open intervals
|
161
|
+
test_files: []
|