fractional 0.1.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1fef2bf465e3f0fb5a870268e07e3f5587d772bf
4
- data.tar.gz: b1a895f28cc4138b09f7ef67570a18689a1771b3
3
+ metadata.gz: e102c37bdea15e535451f4ace3e8427b5cd80ba3
4
+ data.tar.gz: aca489da451ff4ded33297324f3691878696dd8a
5
5
  SHA512:
6
- metadata.gz: 078854ddb0cb3b5aa76b2407fef374bef578e456ff9978da0a1794e37422fe12703a90ffa40a364040551f86354492273fc20aafa246672e999ef10cd9c32992
7
- data.tar.gz: 34812c79b93d3f3b7ab1153e6cee209a17978906363d7ee3527f7e335fcee86c0c23eb3b7d3416f72e9eb14b5ef76833c27a144f64495444d72fc1cded18a135
6
+ metadata.gz: 4dae17fc2ee51bbe1ea07eb0596a759fa5ae34ebd6a9a2418ef9c600c8ff9432a8a5ff354b6f6669edb09f78286e9c8e2432101fbb4712722a66e37eaabf08e5
7
+ data.tar.gz: 8eb87fbff148bee9e9c6c39c860c598aa0fd9adc1741688597666c7c77d1b6550b39d87b650b756678131d112ff3e775590a302ef07999347627b74db7524e5c
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --debug
3
+ --order rand
@@ -1,13 +1,36 @@
1
1
  = Fractional
2
2
 
3
- Fractional is a library for parsing fractions.
3
+ Fractional is a library for parsing, representing and operating on fractions.
4
4
 
5
- Convert fractional string to float:
6
- Fractional.to_f("1100 7/8") #=> 1100.875
5
+ === Conversions
7
6
 
8
- Convert float to fractional string:
9
- Fractional.to_s(1100.875) #=> "1100 7/8"
10
- Fractional.to_s(1100.875, :to_nearest => "1/2") #=> "1101"
7
+ Convert fractional strings to floats:
8
+ Fractional.new("1100 7/8").to_f #=> 1100.875
9
+
10
+ Convert floats to fractional strings:
11
+ Fractional.new(1100.875).to_s #=> "1100 7/8"
12
+ Fractional.new(1100.875, :to_nearest => "1/2").to_s #=> "1101"
13
+
14
+ Also does a great job of guessing repeating decimal values:
15
+ Fractional.new(0.33333).to_s #=> "1/3"
16
+ Fractional.new(3.142857142857).to_s #=> "22/7"
17
+ If you want to prevent this "guesswork" pass the :exact option
18
+ Fractional.new(0.33333, exact: true).to_s #=> "33333/100000"
19
+
20
+ It can render back out mixed numbers:
21
+ Fractional.new(1.45).to_s #=> "29/20"
22
+ Fractional.new(1.45).to_s( mixed_number: true ) #=> "1 9/20"
23
+
24
+
25
+ === Math and Comparisons
26
+ It will integrate nicely with Numerics:
27
+ a = Fractional.new("3/4")
28
+ puts a + 1.5 #=> "9/4"
29
+
30
+ And you can compare it to other Numerics:
31
+ puts Fractional.new("3/4") > -2.3 #=> true
32
+
33
+ === Rounding
11
34
 
12
35
  Round a value to the nearest fraction:
13
36
  Fractional.round_to_nearest_fraction("1100 1/7", "1/64") #=> "1100 9/64"
@@ -28,6 +51,7 @@ Thanks to Jannis Harder for his hardcore float to rational method I nicked from
28
51
 
29
52
  = Contributors
30
53
  Joey Aghion https://github.com/joeyAghion
54
+
31
55
  muff1nman https://github.com/muff1nman
32
56
 
33
57
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 1.0.1
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "fractional"
3
- spec.version = "0.1.0"
3
+ spec.version = "1.0.1"
4
4
  spec.authors = ["Chris O'Sullivan"]
5
5
  spec.email = ["thechrisoshow@gmail.com"]
6
6
  spec.description = %q{Fractional is a Ruby library for parsing fractions.}
@@ -16,4 +16,5 @@ Gem::Specification.new do |spec|
16
16
  spec.add_development_dependency "bundler", "~> 1.3"
17
17
  spec.add_development_dependency "rake"
18
18
  spec.add_development_dependency "rspec"
19
+ spec.add_development_dependency "debugger"
19
20
  end
@@ -0,0 +1,33 @@
1
+ module DeprecatedFractionalMethods
2
+
3
+ def to_f(value)
4
+ warn("Fractional.to_f will be removed in v1.1.")
5
+ string_to_fraction(value).to_f
6
+ end
7
+
8
+ def to_s(value, options={})
9
+ warn("Fractional.to_s will be removed in v1.1\nUse Fractional.new(value).to_s instead.")
10
+ new(float_to_fraction(value)).to_s(options)
11
+ end
12
+
13
+ def fraction?(value)
14
+ warn("Fractional.fraction? will be removed in v1.1\nUse Fractional.string_is_fraction? instead.")
15
+ string_is_fraction?(value)
16
+ end
17
+
18
+ def mixed_fraction?(value)
19
+ warn("Fractional.mixed_fraction? will be removed in v1.1\nUse Fractional.string_is_mixed_fraction? instead.")
20
+ string_is_mixed_fraction?(value)
21
+ end
22
+
23
+ def single_fraction?(value)
24
+ warn("Fractional.single_fraction? will be removed in v1.1\nUse Fractional.string_is_single_fraction? instead.")
25
+ string_is_single_fraction?(value)
26
+ end
27
+
28
+ private
29
+ def warn(message)
30
+ $stderr.puts "\n*** Fractional deprecation warning: #{message}\n\n"
31
+ end
32
+
33
+ end
@@ -1,119 +1,220 @@
1
1
  require 'rational'
2
+ require 'deprecated'
3
+
4
+ class Fractional < Numeric
5
+ extend DeprecatedFractionalMethods
2
6
 
3
- class Fractional
4
7
  SINGLE_FRACTION = /^\s*(\-?\d+)\/(\-?\d+)\s*$/
5
8
  MIXED_FRACTION = /^\s*(\-?\d*)\s+(\d+)\/(\d+)\s*$/
6
9
 
7
- def initialize(value)
8
- @value = value
10
+ def initialize( value, options={} )
11
+ case value
12
+ when Rational
13
+ @value = value
14
+ when String
15
+ @value = Fractional.string_to_fraction( value, options )
16
+ when Fixnum
17
+ @value = Rational(value)
18
+ when Numeric
19
+ @value = Fractional.float_to_fraction( value.to_f, options )
20
+ else
21
+ raise TypeError, "Cannot instantiate Fractional from #{value.class}"
22
+ end
23
+
9
24
  end
10
25
 
11
- def to_s
12
- @value
26
+ def method_missing(name, *args, &blk)
27
+ return_value = @value.send(name, *args, &blk)
28
+ return_value.is_a?(Rational) ? Fractional.new(return_value) : return_value
29
+ end
30
+
31
+ def to_s( options={} )
32
+ if options[:mixed_fraction] or options[:mixed_number]
33
+ to_join = []
34
+ if whole_part != 0
35
+ to_join << whole_part.to_s
36
+ end
37
+ if fractional_part != 0
38
+ to_join << fractional_part.abs.to_s
39
+ end
40
+ to_join.join(" ")
41
+ else
42
+ @value.to_s
43
+ end
13
44
  end
14
45
 
15
46
  def to_f
16
- Fractional.to_f(@value)
47
+ @value.to_f
17
48
  end
18
49
 
19
- [:+, :-, :*, :/].each do |math_operator|
20
- define_method(math_operator) do |another_fractional|
21
- Fractional.new(Fractional.to_s(self.to_f.send(math_operator, another_fractional.to_f)))
22
- end
50
+ def to_r
51
+ @value
23
52
  end
24
53
 
25
- def self.to_f(value)
26
- result = 0
54
+ def to_i
55
+ whole_part
56
+ end
27
57
 
28
- if mixed_fraction?(value)
29
- whole, numerator, denominator = value.scan(MIXED_FRACTION).flatten
58
+ def whole_part
59
+ @value.truncate
60
+ end
30
61
 
31
- result = (numerator.to_f / denominator.to_f) + whole.to_f.abs
62
+ def fractional_part
63
+ @value - whole_part
64
+ end
32
65
 
33
- result = whole.to_f > 0 ? result : -result
34
- elsif single_fraction?(value)
35
- numerator, denominator = value.split("/")
36
- result = numerator.to_f / denominator.to_f
66
+ def ==( other_num )
67
+ @value == other_num
68
+ end
69
+
70
+ def <=>(other)
71
+ case other
72
+ when Fractional, Rational
73
+ self.to_r <=> other.to_r
74
+ when Numeric
75
+ @value <=> other
76
+ when String
77
+ @value <=> Fractional.new(other).to_r
37
78
  else
38
- result = value.to_f
79
+ nil
39
80
  end
40
-
41
- result
42
81
  end
43
82
 
44
- def self.to_s(value, args={})
45
- whole_number = value.to_f.truncate.to_i
46
-
47
- if whole_number == 0 # Single fraction
48
- fractional_part_to_string(value, args[:to_nearest])
49
- else # Mixed fraction
50
- decimal_point_value = get_decimal_point_value(value.to_f)
51
- return whole_number.to_s if decimal_point_value == 0
83
+ def coerce(other)
84
+ case other
85
+ when Numeric
86
+ return Fractional.new(other), self
87
+ when String
88
+ return Fractional.new(other), self
89
+ else
90
+ raise TypeError, "#{other.class} cannot be coerced into #{Numeric}"
91
+ end
92
+ end
52
93
 
53
- fractional_part = fractional_part_to_string(decimal_point_value.abs, args[:to_nearest])
54
94
 
55
- if (fractional_part == "1") || (fractional_part == "0")
56
- (whole_number + fractional_part.to_i).to_s
95
+ [:+, :-, :*, :/, :**].each do |math_operator|
96
+ define_method(math_operator) do |another_fractional|
97
+ if another_fractional.is_a? Fractional or another_fractional.is_a? Rational
98
+ Fractional.new(@value.send(math_operator, another_fractional.to_r))
99
+ elsif another_fractional.is_a? Numeric
100
+ self.send(math_operator, Fractional.new(another_fractional))
57
101
  else
58
- whole_number.to_s + " " + fractional_part
102
+ Fractional.new(self.to_r.send(math_operator, another_fractional))
59
103
  end
60
104
  end
61
105
  end
62
106
 
63
- def self.round_to_nearest_fraction(value, to_nearest_fraction)
64
- if value.is_a? String
65
- to_nearest_float = to_f(to_nearest_fraction)
107
+ def self.float_to_fraction( value, options={} )
108
+ if value.to_f.nan?
109
+ return Rational(0,0) # Div by zero error
110
+ elsif value.to_f.infinite?
111
+ return Rational(value<0 ? -1 : 1,0) # Div by zero error
112
+ end
66
113
 
67
- to_s((self.to_f(value) / to_nearest_float).round * to_nearest_float)
68
- else
69
- to_nearest_float = to_f(to_nearest_fraction)
114
+ if options[:to_nearest]
115
+ return self.round_to_nearest_fraction( value, options[:to_nearest] )
116
+ end
70
117
 
71
- (value / to_nearest_float).round * to_nearest_float
118
+ # first try to convert a repeating decimal unless guesstimate is forbidden
119
+ unless options[:exact]
120
+ repeat = float_to_rational_repeat(value)
121
+ return repeat unless repeat.nil?
72
122
  end
73
123
 
124
+ # finally assume a simple decimal
125
+ # The to_s helps with float rounding issues
126
+ return Rational(value.to_s)
127
+
74
128
  end
75
129
 
76
- private
130
+ def self.string_to_fraction( value, options={} )
131
+ if string_is_mixed_fraction?(value)
132
+ whole, numerator, denominator = value.scan(MIXED_FRACTION).flatten
133
+ return Rational( (whole.to_i.abs * denominator.to_i + numerator.to_i) *
134
+ whole.to_i / whole.to_i.abs, denominator.to_i )
135
+ elsif string_is_single_fraction?(value)
136
+ numerator, denominator = value.split("/")
137
+ return Rational(numerator.to_i, denominator.to_i)
138
+ else
139
+ return float_to_fraction(value.to_f, options)
140
+ end
141
+ end
77
142
 
78
- def self.fraction?(value)
143
+ def self.string_is_fraction?( value )
79
144
  value.is_a? String and (value.match(SINGLE_FRACTION) or value.match(MIXED_FRACTION))
80
145
  end
81
146
 
82
- def self.single_fraction?(value)
83
- fraction?(value) and value.match(SINGLE_FRACTION)
147
+ def self.string_is_mixed_fraction?( value )
148
+ string_is_fraction?(value) and value.match(MIXED_FRACTION)
84
149
  end
85
150
 
86
- def self.mixed_fraction?(value)
87
- fraction?(value) and value.match(MIXED_FRACTION)
151
+ def self.string_is_single_fraction?( value )
152
+ string_is_fraction?(value) and value.match(SINGLE_FRACTION)
153
+ end
154
+
155
+ def self.float_to_rational_repeat(base_value)
156
+ normalized_value = base_value.to_f
157
+ repeat = find_repeat( normalized_value )
158
+
159
+ if repeat.nil? or repeat.length < 1
160
+ # try again chomping off the last number (fixes float rounding issues)
161
+ normalized_value = normalized_value.to_s[0...-1].to_f
162
+ repeat = find_repeat(normalized_value.to_s)
163
+ end
164
+
165
+ if !repeat or repeat.length < 1
166
+ return nil
167
+ else
168
+ return fractional_from_parts(
169
+ find_before_decimal(normalized_value),
170
+ find_after_decimal(normalized_value),
171
+ repeat)
172
+ end
88
173
  end
89
174
 
90
- def self.get_decimal_point_value(value)
91
- value - value.truncate
175
+ def self.find_after_decimal( decimal )
176
+ s_decimal = decimal.to_s
177
+ regex = /(#{find_repeat(s_decimal)})+/
178
+ last = s_decimal.index( regex )
179
+ first = s_decimal.index( '.' ) + 1
180
+ s_decimal[first...last]
92
181
  end
93
182
 
94
- def self.fractional_part_to_string(value, round)
95
- if round
96
- round_to_nearest_fraction(float_to_rational(value.to_f).to_s, round)
183
+ def self.find_before_decimal( decimal )
184
+ numeric = decimal.to_f.truncate.to_i
185
+ if numeric == 0
186
+ decimal.to_f < 0 ? "-0" : "0"
97
187
  else
98
- float_to_rational(value.to_f).to_s
188
+ numeric.to_s
99
189
  end
100
190
  end
101
191
 
102
- # Whoa this method is crazy
103
- # I nicked it from Jannis Harder at http://markmail.org/message/nqgrsmaixwbrvsno
104
- def self.float_to_rational(value)
105
- if value.nan?
106
- return Rational(0,0) # Div by zero error
107
- elsif value.infinite?
108
- return Rational(value<0 ? -1 : 1,0) # Div by zero error
192
+ def self.find_repeat( decimal )
193
+ return largest_repeat( decimal.to_s.reverse, 0 ).reverse
194
+ end
195
+
196
+ def self.largest_repeat( string, i )
197
+ if i * 2 > string.length
198
+ return ""
109
199
  end
110
- s,e,f = [value].pack("G").unpack("B*").first.unpack("AA11A52")
111
- s = (-1)**s.to_i
112
- e = e.to_i(2)
113
- if e.nonzero? and e<2047
114
- Rational(s)* Rational(2)**(e-1023)*Rational("1#{f}".to_i(2),0x10000000000000)
115
- elsif e.zero?
116
- Rational(s)* Rational(2)**(-1024)*Rational("0#{f}".to_i(2),0x10000000000000)
200
+ repeat_string = string[0..i]
201
+ next_best = largest_repeat( string, i + 1)
202
+ if repeat_string == string[i+1..2*i + 1]
203
+ repeat_string.length > next_best.length ? repeat_string : next_best
204
+ else
205
+ next_best
117
206
  end
118
207
  end
208
+
209
+ def self.fractional_from_parts(before_decimal, after_decimal, repeat)
210
+ numerator = "#{before_decimal}#{after_decimal}#{repeat}".to_i - "#{before_decimal}#{after_decimal}".to_i
211
+ denominator = 10 ** (after_decimal.length + repeat.length) - 10 ** after_decimal.length
212
+ return Rational( numerator, denominator )
213
+ end
214
+
215
+ def self.round_to_nearest_fraction(value, to_nearest_fraction)
216
+ to_nearest_float = Fractional.new(to_nearest_fraction).to_f
217
+ Fractional.new((Fractional.new(value).to_f / to_nearest_float).round * to_nearest_float)
218
+ end
219
+
119
220
  end
@@ -1,54 +1,486 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
- describe "Fractional" do
3
+ ##################################
4
+ # CLASS METHODS #
5
+ ##################################
6
+ describe "Fractional::new" do
7
+ it "should accept Rationals" do
8
+ Fractional.new(Rational(3,4)).should_not be_nil
9
+ end
10
+
11
+ it "should accept strings" do
12
+ Fractional.new("3/4").should_not be_nil
13
+ end
14
+
15
+ it "should accept floats" do
16
+ Fractional.new(0.75).should_not be_nil
17
+ end
18
+
19
+ it "should pass options down (such as exact)" do
20
+ Fractional.new(0.333, exact: true).should_not == Rational(1,3)
21
+ Fractional.new("0.333", exact: true).should_not == Rational(1,3)
22
+ end
23
+
24
+ end
25
+
26
+ describe "Fractional::float_to_fractional" do
27
+ it "should parse simple decimals" do
28
+ Fractional.float_to_fraction(0.5).should == Fractional.new(Rational(1,2))
29
+ Fractional.float_to_fraction(1.5).should == Fractional.new(Rational(3,2))
30
+ Fractional.float_to_fraction(1100).should == Fractional.new(Rational(1100,1))
31
+ # This next example is especially important as Rational(1.2) is not a nice
32
+ # number.
33
+ Fractional.float_to_fraction(1.2).should == Fractional.new(Rational(6,5))
34
+ end
35
+
36
+ it "should parse more complex decimals" do
37
+ Fractional.float_to_fraction(1100.875).should == Fractional.new(Rational(8807,8))
38
+ end
39
+
40
+ it "should allow for negative values for mixed fractions" do
41
+ Fractional.float_to_fraction(-1100.875).should == Fractional.new(Rational(-8807,8))
42
+ end
43
+
44
+ it "should allow for negative values for single fractions" do
45
+ Fractional.float_to_fraction(-0.875).should == Fractional.new(Rational(-7,8))
46
+ end
47
+
48
+ it "should allow for negative mixed fractions that that are rounded" do
49
+ Fractional.float_to_fraction(-101.140625, :to_nearest => "1/64").should == Fractional.new("-101 9/64")
50
+ end
51
+
52
+ it "should allow for negative single fractions that that are rounded" do
53
+ Fractional.float_to_fraction(-0.140625, :to_nearest => "1/64").should == Fractional.new("-9/64")
54
+ end
55
+
56
+ it "should round if passed 'to nearest'" do
57
+ Fractional.float_to_fraction(1100.14285714286, :to_nearest => "1/64").should == Fractional.new("1100 9/64")
58
+ end
59
+
60
+ it "should round if passed 'to_nearest' that is a float" do
61
+ Fractional.float_to_fraction(1100.14285714286, :to_nearest => 0.015625).should == Fractional.new("1100 9/64")
62
+ end
63
+
64
+ it "should round if passed 'to_nearest' and is a simple fraction" do
65
+ Fractional.float_to_fraction(0.14285714286, :to_nearest => "1/64").should == Fractional.new("9/64")
66
+ end
67
+
68
+ it "should round if passed 'to_nearest' that rounds to nearest whole number" do
69
+ Fractional.float_to_fraction(1100.875, :to_nearest => "1/2").should == Fractional.new("1101")
70
+ Fractional.float_to_fraction(1100.2, :to_nearest => "1/2").should == Fractional.new("1100")
71
+ end
72
+
73
+ end
74
+
75
+ describe "Fractional::string_to_fractional" do
76
+ it "should parse a single fraction" do
77
+ Fractional.string_to_fraction('1/2').should == Fractional.new(Rational(1,2))
78
+ end
79
+
80
+ it "should parse a mixed fraction" do
81
+ Fractional.string_to_fraction('1 2/4').should == Fractional.new(Rational(3,2))
82
+ Fractional.string_to_fraction("1100 7/8").should == Fractional.new(Rational(8807,8))
83
+ end
84
+
85
+ it "should parse a simple decimal" do
86
+ Fractional.string_to_fraction('1.5').should == Fractional.new(Rational(3,2))
87
+ end
88
+
89
+ it "should allow for negative mixed fractions" do
90
+ Fractional.string_to_fraction('-10 1/2').should == Fractional.new(Rational(-21,2))
91
+ end
92
+
93
+ it "should allow for negative single fractions" do
94
+ Fractional.string_to_fraction("-1/64").should == Fractional.new(Rational(-1,64))
95
+ end
96
+
97
+ it "should allow for negative denominators in single fractions" do
98
+ Fractional.string_to_fraction("1/-64").should == Fractional.new(Rational(-1,64))
99
+ Fractional.string_to_fraction("-1/-64").should == Fractional.new(Rational(1,64))
100
+ end
101
+
102
+ it "should ignore repeated whitespace" do
103
+ Fractional.string_to_fraction("6 5/8").should == Fractional.string_to_fraction("6 5/8")
104
+ end
105
+
106
+ it "should try to get an accurate estimation of floating point values by default" do
107
+ Fractional.string_to_fraction("0.3333").should == Fractional.float_to_fraction(0.33333)
108
+ end
109
+
110
+ it "should not estimate if exact is specified" do
111
+ Fractional.string_to_fraction("0.3333", exact: true).should_not == Rational(1,3)
112
+ end
113
+
114
+ end
115
+
116
+ describe "Fractional::string_is_fraction?" do
117
+ it "should recognize a simple fraction" do
118
+ Fractional.string_is_fraction?("3/4").should be_true
119
+ end
120
+
121
+ it "should recognize a mixed fraction" do
122
+ Fractional.string_is_fraction?("1 11/12").should be_true
123
+ end
124
+
125
+ it "should recognize a negative fraction" do
126
+ Fractional.string_is_fraction?("-3/4").should be_true
127
+ end
128
+
129
+ it "should recognize a negative mixed fraction" do
130
+ Fractional.string_is_fraction?("-6 2/9").should be_true
131
+ end
132
+
133
+ it "should accept more than one space between the whole number and fractional part" do
134
+ Fractional.string_is_fraction?("1 2/3").should be_true
135
+ Fractional.string_is_fraction?("3 1/2").should be_true
136
+ end
137
+
138
+ it "should accept fractions with front and rear padding" do
139
+ Fractional.string_is_fraction?(" 2/3").should be_true
140
+ Fractional.string_is_fraction?("2/3 ").should be_true
141
+ Fractional.string_is_fraction?(" 2/3 ").should be_true
142
+ Fractional.string_is_fraction?(" 1 2/3").should be_true
143
+ Fractional.string_is_fraction?("1 2/3 ").should be_true
144
+ Fractional.string_is_fraction?(" 1 2/3 ").should be_true
145
+ end
146
+
147
+ it "should not recognize decimals" do
148
+ Fractional.string_is_fraction?("2.3").should be_false
149
+ end
150
+
151
+ it "should not recognize two consecutive fractions" do
152
+ Fractional.string_is_fraction?("2/3 9/5").should be_false
153
+ end
154
+
155
+ it "should not recognize a string with a slash" do
156
+ Fractional.string_is_fraction?("n/a").should be_false
157
+ end
158
+
159
+ it "should not recognize a fraction mixed with non-decimals" do
160
+ Fractional.string_is_fraction?("3a/4").should be_false
161
+ Fractional.string_is_fraction?("a2/3").should be_false
162
+ Fractional.string_is_fraction?("1 2/3a").should be_false
163
+ end
164
+
165
+ it "should not recognize fractions with improper spacing" do
166
+ Fractional.string_is_fraction?("2 /2").should be_false
167
+ Fractional.string_is_fraction?("1/ 3").should be_false
168
+ Fractional.string_is_fraction?("1 2/ 3").should be_false
169
+ Fractional.string_is_fraction?("1 2 /3").should be_false
170
+ end
171
+
172
+ end
173
+
174
+ describe "Fractional::string_is_mixed_fraction?" do
175
+ it "should recognize a mixed fraction" do
176
+ Fractional.string_is_mixed_fraction?("1 11/12").should be_true
177
+ end
178
+
179
+ it "should recognize a negative mixed fraciton" do
180
+ Fractional.string_is_mixed_fraction?("-1 11/12").should be_true
181
+ end
182
+
183
+ it "should not recognize a single fraction" do
184
+ Fractional.string_is_mixed_fraction?("3/4").should be_false
185
+ end
186
+
187
+ end
188
+
189
+ describe "Fractional::string_is_single_fraction?" do
190
+ it "should recognize a single fraction" do
191
+ Fractional.string_is_single_fraction?("3/4").should be_true
192
+ end
193
+
194
+ it "should recognize a negative numerator with a single fraction" do
195
+ Fractional.string_is_single_fraction?("-3/4").should be_true
196
+ end
197
+
198
+ it "should not recognize a mixed fraction" do
199
+ Fractional.string_is_single_fraction?("1 11/12").should be_false
200
+ end
201
+
202
+ it "should allow for negative denominators in single fractions" do
203
+ Fractional.string_is_single_fraction?("1/-64").should be_true
204
+ Fractional.string_is_single_fraction?("-1/-64").should be_true
205
+ end
206
+
207
+ end
208
+
209
+ describe "Frational", "fractional_from_parts" do
210
+ it "should return rational values for various decimals" do
211
+ Fractional.fractional_from_parts("","","3").should eq(Rational(1,3))
212
+ Fractional.fractional_from_parts("","","7").should eq(Rational(7,9))
213
+ Fractional.fractional_from_parts("","","9").should eq(Rational(1,1))
214
+ Fractional.fractional_from_parts("5","8","144").should eq(Rational(3227,555))
215
+ Fractional.fractional_from_parts("","58","3").should eq(Rational(7,12))
216
+ Fractional.fractional_from_parts("","","012345679").should eq(Rational(1,81))
217
+ Fractional.fractional_from_parts("-0","","3333").should eq(Rational(-1,3))
218
+ end
219
+ end
220
+
221
+ describe "Fractional", "find_repeat" do
222
+ it "should return the repeating decimals in a string" do
223
+ Fractional.find_repeat("1.0333").should eq("3")
224
+ Fractional.find_repeat("0.333").should eq("3")
225
+ Fractional.find_repeat("3.142857142857").should eq("142857")
226
+ end
227
+
228
+ it "should return nil when there are not enough repeating decimals" do
229
+ Fractional.find_repeat("1.03").should eq("")
230
+ end
231
+ end
232
+
233
+ describe "Fractional", "find_after_decimal" do
234
+ it "should return the decimal characters after the decimal but before the repeating characters" do
235
+ Fractional.find_after_decimal("1.0333").should eq("0")
236
+ Fractional.find_after_decimal("0.3333").should eq("")
237
+ Fractional.find_after_decimal("0.58333").should eq("58")
238
+ end
239
+ end
240
+
241
+
242
+ describe "Fractional", "find_before_decimal" do
243
+ it "should return the decimal characters before the decimal" do
244
+ Fractional.find_before_decimal("1.0333").should eq("1")
245
+ Fractional.find_before_decimal(".3333").should eq("0")
246
+ Fractional.find_before_decimal("-1.4444").should eq("-1")
247
+ Fractional.find_before_decimal("-0.4444").should eq("-0")
248
+ end
249
+ end
250
+
251
+ describe "Fractional", "float_to_rational_repeat" do
252
+ it "should parse a repeating decimal into a fractional value" do
253
+ Fractional.float_to_rational_repeat("0.33").should eq(Rational(1,3))
254
+ Fractional.float_to_rational_repeat(".33").should eq(Rational(1,3))
255
+ Fractional.float_to_rational_repeat("0.8181").should eq(Rational(9,11))
256
+ Fractional.float_to_rational_repeat("3.142857142857").should eq(Rational(22,7))
257
+ Fractional.float_to_rational_repeat("-0.33333").should eq(Rational(-1,3))
258
+ end
259
+
260
+ it "should be able to deal with a rounding error at the end of a float value" do
261
+ Fractional.string_to_fraction("3.1666666666666665").should eq(Rational(19,6))
262
+ end
263
+
264
+ it "should not be able to parse a non repeating decimal" do
265
+ Fractional.float_to_rational_repeat("1.234").should be_nil
266
+ Fractional.float_to_rational_repeat("1.333312").should be_nil
267
+ Fractional.float_to_rational_repeat("as2342").should be_nil
268
+ end
269
+ end
4
270
 
5
- it "should create a fractional object from a string" do
6
- one_half = Fractional.new("1/2")
271
+
272
+ ##################################
273
+ # Arithematic #
274
+ ##################################
275
+
276
+ describe "Fractional#+" do
277
+ it "should add with another Fractional" do
278
+ (Fractional.new(Rational(3,4)) + Fractional.new(Rational(1,2))).should == Fractional.new(1.25)
7
279
  end
8
280
 
9
- it "should create a fractional object from a string" do
10
- one_half = Fractional.new("1/2")
281
+ it "should add with other numerics" do
282
+ (Fractional.new(Rational(-4,5)) + 1).should == Fractional.new(Rational(1,5))
283
+ (Fractional.new("2/3") + 1.2).should == Fractional.new(1.86666666)
284
+ (Fractional.new(1.3) + BigDecimal.new(2)).should == Fractional.new("3.3")
11
285
  end
12
286
 
13
- it "should create a fractional object from a string" do
14
- one_half = Fractional.new("1/2")
287
+ it "should add with other numerics when other numerics are specified first" do
288
+ (1 + Fractional.new(Rational(-4,5)) ).should == Fractional.new(Rational(1,5))
289
+ (1.2 + Fractional.new("2/3")).should == Fractional.new(1.86666666)
290
+ (BigDecimal.new(2) + Fractional.new(1.3)).should == Fractional.new("3.3")
15
291
  end
16
-
17
- it "should convert fractional to string" do
18
- one_half = Fractional.new("1/2")
19
- one_half.to_s.should == "1/2"
292
+ end
293
+
294
+ describe "Fractional#-" do
295
+ (1 - Fractional.new(Rational(1,2))).should == Fractional.new(Rational(1,2))
296
+ end
297
+
298
+ describe "Fractional#*" do
299
+ (Fractional.new(Rational(1,2)) * Fractional.new(0.75)).should == Fractional.new(0.375)
300
+ end
301
+
302
+ describe "Fractional#/" do
303
+ (Fractional.new(Rational(4,3)) / Fractional.new(Rational(3,2))).should == Fractional.new(Rational(8,9))
304
+ end
305
+
306
+ describe "Fractional#**" do
307
+ (Fractional.new(8) ** Fractional.new(Rational(1,3))).should == Fractional.new(2)
308
+ end
309
+
310
+ ##################################
311
+ # comparison #
312
+ ##################################
313
+
314
+ describe "Fractional#==" do
315
+ it "should be equal to same Fractions" do
316
+ (Fractional.new(Rational(3,1)) == Fractional.new(Rational(3,1))).should be_true
20
317
  end
21
-
22
- it "should convert fractional to float" do
23
- one_half = Fractional.new("1/2")
24
- one_half.to_f.should == 0.5
318
+
319
+ it "should not be equal to other Fractions" do
320
+ (Fractional.new(Rational(3,2)) == Fractional.new(Rational(3,1))).should be_false
25
321
  end
26
-
27
- it "should add two fractionals together" do
28
- one_half = Fractional.new("1/2")
29
- another_one_half = Fractional.new("1/2")
30
-
31
- (one_half + another_one_half).to_f.should == 1.0
322
+
323
+ it "should be equal regardless of type" do
324
+ (Fractional.new(Rational(3,4)) == Fractional.new(0.75)).should be_true
32
325
  end
326
+ end
33
327
 
34
- it "should minus a fractional from another fractional" do
35
- one_and_a_half = Fractional.new("1 1/2")
36
- one_quarter = Fractional.new("1/4")
37
-
38
- (one_and_a_half - one_quarter).to_f.should == 1.25
328
+ describe "Frational#<=>" do
329
+ it "should return 0 if fractions are equal" do
330
+ (Fractional.new(Rational(5,4)) <=> Fractional.new(1.25)).should == 0
39
331
  end
40
332
 
41
- it "should multiply 2 fractionals together" do
42
- first_fraction = Fractional.new("1 7/8")
43
- second_fraction = Fractional.new("11 15/64")
44
-
45
- (first_fraction * second_fraction).to_f.should == 21.064453125
333
+ it "should return -1 if the lhs is less" do
334
+ (Fractional.new(Rational(3,4)) <=> Fractional.new(Rational(8,9))).should == -1
46
335
  end
47
-
48
- it "should divide 2 fractionals together" do
49
- first_fraction = Fractional.new("1 7/8")
50
- second_fraction = Fractional.new("21 33/512")
51
-
52
- (second_fraction / first_fraction).to_s.should == "11 15/64"
336
+
337
+ it "should compare to other numerics" do
338
+ (Fractional.new(Rational(-1,2)) <=> -0.5).should == 0
339
+ (Fractional.new(Rational(-1,2)) <=> 1).should == -1
340
+ (Fractional.new(Rational(-1,2)) <=> BigDecimal.new(-2)).should == 1
341
+ end
342
+
343
+ it "should work the other way too" do
344
+ ( -0.5 <=> Fractional.new(Rational(-1,2))).should == 0
345
+ (1 <=> Fractional.new(Rational(-1,2))).should == 1
346
+ (BigDecimal.new(-2) <=> Fractional.new(Rational(-1,2))).should == -1
347
+ end
348
+
349
+ it "would be nice to compare to strings" do
350
+ (Fractional.new(Rational(1,2)) <=> "3/4").should == -1
351
+ ("3/4" <=> Fractional.new(Rational(1,2))).should == 1
352
+ ("-3/4" <=> Fractional.new(Rational(-1,2))).should == -1
353
+ end
354
+ end
355
+
356
+ describe "Frational", "comparsion" do
357
+ it "should use the numerics included comparsion module" do
358
+ (Fractional.new(Rational(-3,4)) < Fractional.new(Rational(1,2))).should be_true
359
+ end
360
+ end
361
+
362
+ ##################################
363
+ # conversion #
364
+ ##################################
365
+
366
+ describe "Fractional#to_s" do
367
+ it "should return nice representations of single fractions" do
368
+ Fractional.new(0.75).to_s.should == "3/4"
369
+ Fractional.new(-0.3333).to_s.should == "-1/3"
370
+
371
+ end
372
+
373
+ it "should return nice representations of mixed fractions" do
374
+ Fractional.new(1.5).to_s.should == "3/2"
375
+ Fractional.new(-1.3333).to_s.should == "-4/3"
376
+ Fractional.new(0.0).to_s.should == "0/1"
377
+ end
378
+
379
+ it "should return mixed number representations if told so" do
380
+ Fractional.new(1.5).to_s(mixed_number: true).should == "1 1/2"
381
+ Fractional.new(Rational(-3,2)).to_s(mixed_number: true).should == "-1 1/2"
382
+ Fractional.new(1.00).to_s(mixed_number: true).should == "1"
383
+ Fractional.new(0.75).to_s(mixed_number: true).should == "3/4"
384
+ end
385
+ end
386
+
387
+ describe "Fractional#to_f" do
388
+ it "should return float representations of fractions" do
389
+ Fractional.new("3/4").to_f.should == 0.75
390
+ Fractional.new("-2/3").to_f.should be_within(0.0000001).of(-0.6666666)
391
+ end
392
+ end
393
+
394
+ describe "Fractional#to_r" do
395
+ it "should return a rational representation" do
396
+ Fractional.new("3/4").to_r.should == Rational(3,4)
397
+ end
398
+ end
399
+
400
+ describe "Fractional#to_i" do
401
+ it "should return a truncated value" do
402
+ Fractional.new("1 3/4").to_i.should == 1
403
+ Fractional.new("-2 1/3").to_i.should == -2
404
+ end
405
+ end
406
+
407
+ describe "Fractional", "round" do
408
+
409
+ it "should round 0.142857142857143 to nearest 1/64th as 0.140625" do
410
+ Fractional.round_to_nearest_fraction(0.142857142857143, "1/64").should == Fractional.new(0.140625)
411
+ end
412
+
413
+ it "should round '1/7' to nearest 1/64th as '9/64'" do
414
+ Fractional.round_to_nearest_fraction('1/7', "1/64").should == Fractional.new('9/64')
415
+ end
416
+
417
+ it "should round 0.125 to nearest 1/64th as 0.125" do
418
+ Fractional.round_to_nearest_fraction(0.125, "1/64").should == Fractional.new(0.125)
419
+ end
420
+
421
+ it "should round '1100 1/7' to nearest 1/64th as '1100 9/64'" do
422
+ Fractional.round_to_nearest_fraction('1100 1/7', "1/64").should == Fractional.new('70409/64')
423
+ end
424
+
425
+ it "should round 1100.142857142857143 to nearest 1/64th as 1100.140625" do
426
+ Fractional.round_to_nearest_fraction(1100.142857142857143, "1/64").should == Fractional.new(1100.140625)
427
+ end
428
+
429
+ it "should round if passed 'to_nearest' that rounds to nearest whole number" do
430
+ Fractional.round_to_nearest_fraction(1100.875, "1/2").should == Fractional.new(1101)
431
+ Fractional.round_to_nearest_fraction(1100.1, "1/2").should == Fractional.new(1100)
432
+ end
433
+
434
+ it "should round if passed a float" do
435
+ Fractional.round_to_nearest_fraction(1100.875, 0.5).should == Fractional.new(1101)
436
+ end
437
+ end
438
+
439
+ ##################################
440
+ # misc #
441
+ ##################################
442
+
443
+ describe 'Fractional#whole_part' do
444
+ it "should return the whole part, if it exists, of a fraction" do
445
+ Fractional.new(Rational(3,2)).whole_part.should eq(1)
446
+ Fractional.new(Rational(-3,2)).whole_part.should eq(-1)
447
+ Fractional.new(Rational(1,2)).whole_part.should eq(0)
448
+ end
449
+ end
450
+
451
+ describe 'Fractional#fractional_part' do
452
+ it "should return the fractional part, if it exists, of a fraction" do
453
+ Fractional.new(Rational(3,2)).fractional_part.should eq(Fractional.new(Rational(1,2)))
454
+ Fractional.new(Rational(-3,2)).fractional_part.should eq(Fractional.new(Rational(-1,2)))
455
+ Fractional.new(Rational(1,2)).fractional_part.should eq(Fractional.new(Rational(1,2)))
456
+ Fractional.new(Rational(2,2)).fractional_part.should eq(Fractional.new(0))
457
+ end
458
+ end
459
+
460
+
461
+ ##################################
462
+ # deprecated methods #
463
+ ##################################
464
+ # remove in v1.1
465
+ describe "deprecated methods" do
466
+ it "Fractional.to_f" do
467
+ Fractional.to_f(1.5).should == 1.5
468
+ end
469
+
470
+ it "Fractional.to_s" do
471
+ Fractional.to_s(0.5).should == '1/2'
472
+ Fractional.to_s(-0.140625, :to_nearest => "1/64").should == "-9/64"
473
+ end
474
+
475
+ it "Fraction.fraction?" do
476
+ Fractional.fraction?("3/4").should be_true
477
+ end
478
+
479
+ it "Fraction.mixed_fraction?" do
480
+ Fractional.mixed_fraction?("1 11/12").should be_true
481
+ end
482
+
483
+ it "Fraction.single_fraction?" do
484
+ Fractional.single_fraction?("-3/4").should be_true
53
485
  end
54
486
  end
@@ -1,5 +1,6 @@
1
1
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  require 'fractional'
3
+ require 'bigdecimal'
3
4
 
4
5
  RSpec.configure do |config|
5
6
  config.treat_symbols_as_metadata_keys_with_true_values = true
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fractional
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris O'Sullivan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-05-11 00:00:00.000000000 Z
11
+ date: 2013-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: debugger
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  description: Fractional is a Ruby library for parsing fractions.
56
70
  email:
57
71
  - thechrisoshow@gmail.com
@@ -60,14 +74,15 @@ extensions: []
60
74
  extra_rdoc_files: []
61
75
  files:
62
76
  - .gitignore
77
+ - .rspec
63
78
  - Gemfile
64
79
  - LICENSE
65
80
  - README.rdoc
66
81
  - Rakefile
67
82
  - VERSION
68
83
  - fractional.gemspec
84
+ - lib/deprecated.rb
69
85
  - lib/fractional.rb
70
- - spec/fractional_class_methods_spec.rb
71
86
  - spec/fractional_spec.rb
72
87
  - spec/spec_helper.rb
73
88
  homepage: http://github.com/thechrisoshow/fractional
@@ -96,6 +111,5 @@ specification_version: 4
96
111
  summary: 'You can use fractional to convert decimal numbers to string representations
97
112
  of fractions. e.g: Fractional.to_s(1.5) #=> "1 1/2"'
98
113
  test_files:
99
- - spec/fractional_class_methods_spec.rb
100
114
  - spec/fractional_spec.rb
101
115
  - spec/spec_helper.rb
@@ -1,219 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
-
3
- describe "Fractional", "to_f" do
4
-
5
- it "should parse '1/2' to 0.5" do
6
- Fractional.to_f('1/2').should == 0.5
7
- end
8
-
9
- it "should parse '1 2/4' to 1.5" do
10
- Fractional.to_f('1 2/4').should == 1.5
11
- end
12
-
13
- it "should parse '1.5' to 1.5" do
14
- Fractional.to_f('1.5').should == 1.5
15
- end
16
-
17
- it "should parse 1.5 to 1.5" do
18
- Fractional.to_f(1.5).should == 1.5
19
- end
20
-
21
- it "should parse '1100 7/8' to 1100.875" do
22
- Fractional.to_f("1100 7/8").should == 1100.875
23
- end
24
-
25
- it "should allow for negative mixed fractions" do
26
- Fractional.to_f('-10 1/2').should == -10.5
27
- end
28
-
29
- it "should allow for negative single fractions" do
30
- Fractional.to_f("-1/64").should == -0.015625
31
- end
32
-
33
- it "should allow for negative denominators in single fractions" do
34
- Fractional.to_f("1/-64").should == -0.015625
35
- Fractional.to_f("-1/-64").should == 0.015625
36
- end
37
-
38
- it "should ignore repeated whitespace" do
39
- Fractional.to_f("6 5/8").should == Fractional.to_f("6 5/8")
40
- end
41
- end
42
-
43
- describe "Fractional", "to_s" do
44
-
45
- it "should return 0.5 as '1/2'" do
46
- Fractional.to_s(0.5).should == '1/2'
47
- end
48
-
49
- it "should return 1.5 as '1 1/2'" do
50
- Fractional.to_s(1.5).should == '1 1/2'
51
- end
52
-
53
- it "should parse 1100.875 to '1100 7/8'" do
54
- Fractional.to_s(1100.875).should == "1100 7/8"
55
- end
56
-
57
- it "should not have a fraction if it's just a whole number" do
58
- Fractional.to_s(1100).should == "1100"
59
- end
60
-
61
- it "should round if passed 'to nearest'" do
62
- Fractional.to_s(1100.14285714286, :to_nearest => "1/64").should == "1100 9/64"
63
- end
64
-
65
- it "should round if passed 'to_nearest' that is a float" do
66
- Fractional.to_s(1100.14285714286, :to_nearest => 0.015625).should == "1100 9/64"
67
- end
68
-
69
- it "should round if passed 'to_nearest' and is a simple fraction" do
70
- Fractional.to_s(0.14285714286, :to_nearest => "1/64").should == "9/64"
71
- end
72
-
73
- it "should round if passed 'to_nearest' that rounds to nearest whole number" do
74
- Fractional.to_s(1100.875, :to_nearest => "1/2").should == "1101"
75
- Fractional.to_s(1100.2, :to_nearest => "1/2").should == "1100"
76
- end
77
-
78
- it "should allow for negative values for mixed fractions" do
79
- Fractional.to_s(-1100.875).should == "-1100 7/8"
80
- end
81
-
82
- it "should allow for negative values for single fractions" do
83
- Fractional.to_s(-0.875).should == "-7/8"
84
- end
85
-
86
- it "should allow for negative mixed fractions that that are rounded" do
87
- Fractional.to_s(-101.140625, :to_nearest => "1/64").should == "-101 9/64"
88
- end
89
-
90
- it "should allow for negative single fractions that that are rounded" do
91
- Fractional.to_s(-0.140625, :to_nearest => "1/64").should == "-9/64"
92
- end
93
-
94
-
95
- end
96
-
97
- describe "Fractional", "round" do
98
-
99
- it "should round 0.142857142857143 to nearest 1/64th as 0.140625" do
100
- Fractional.round_to_nearest_fraction(0.142857142857143, "1/64").should == 0.140625
101
- end
102
-
103
- it "should round '1/7' to nearest 1/64th as '9/64'" do
104
- Fractional.round_to_nearest_fraction('1/7', "1/64").should == '9/64'
105
- end
106
-
107
- it "should round 0.125 to nearest 1/64th as 0.125" do
108
- Fractional.round_to_nearest_fraction(0.125, "1/64").should == 0.125
109
- end
110
-
111
- it "should round '1100 1/7' to nearest 1/64th as '1100 9/64'" do
112
- Fractional.round_to_nearest_fraction('1100 1/7', "1/64").should == '1100 9/64'
113
- end
114
-
115
- it "should round 1100.142857142857143 to nearest 1/64th as 1100.140625" do
116
- Fractional.round_to_nearest_fraction(1100.142857142857143, "1/64").should == 1100.140625
117
- end
118
-
119
- it "should round if passed 'to_nearest' that rounds to nearest whole number" do
120
- Fractional.round_to_nearest_fraction(1100.875, "1/2").should == 1101
121
- Fractional.round_to_nearest_fraction(1100.1, "1/2").should == 1100
122
- end
123
-
124
- it "should round if passed a float" do
125
- Fractional.round_to_nearest_fraction(1100.875, 0.5).should == 1101
126
- end
127
- end
128
-
129
- describe "Fractional", "fraction?" do
130
- it "should recognize a simple fraction" do
131
- Fractional.fraction?("3/4").should be_true
132
- end
133
-
134
- it "should recognize a mixed fraction" do
135
- Fractional.fraction?("1 11/12").should be_true
136
- end
137
-
138
- it "should recognize a negative fraction" do
139
- Fractional.fraction?("-3/4").should be_true
140
- end
141
-
142
- it "should recognize a negative mixed fraction" do
143
- Fractional.fraction?("-6 2/9").should be_true
144
- end
145
-
146
- it "should accept more than one space between the whole number and fractional part" do
147
- Fractional.fraction?("1 2/3").should be_true
148
- Fractional.fraction?("3 1/2").should be_true
149
- end
150
-
151
- it "should accept fractions with front and rear padding" do
152
- Fractional.fraction?(" 2/3").should be_true
153
- Fractional.fraction?("2/3 ").should be_true
154
- Fractional.fraction?(" 2/3 ").should be_true
155
- Fractional.fraction?(" 1 2/3").should be_true
156
- Fractional.fraction?("1 2/3 ").should be_true
157
- Fractional.fraction?(" 1 2/3 ").should be_true
158
- end
159
-
160
- it "should not recognize decimals" do
161
- Fractional.fraction?("2.3").should be_false
162
- end
163
-
164
- it "should not recognize two consecutive fractions" do
165
- Fractional.fraction?("2/3 9/5").should be_false
166
- end
167
-
168
- it "should not recognize a string with a slash" do
169
- Fractional.fraction?("n/a").should be_false
170
- end
171
-
172
- it "should not recognize a fraction mixed with non-decimals" do
173
- Fractional.fraction?("3a/4").should be_false
174
- Fractional.fraction?("a2/3").should be_false
175
- Fractional.fraction?("1 2/3a").should be_false
176
- end
177
-
178
- it "should not recognize fractions with improper spacing" do
179
- Fractional.fraction?("2 /2").should be_false
180
- Fractional.fraction?("1/ 3").should be_false
181
- Fractional.fraction?("1 2/ 3").should be_false
182
- Fractional.fraction?("1 2 /3").should be_false
183
- end
184
-
185
- end
186
-
187
- describe "Fractional", "single_fraction?" do
188
- it "should recognize a single fraction" do
189
- Fractional.single_fraction?("3/4").should be_true
190
- end
191
-
192
- it "should recognize a negative numerator with a single fraction" do
193
- Fractional.single_fraction?("-3/4").should be_true
194
- end
195
-
196
- it "should not recognize a mixed fraction" do
197
- Fractional.single_fraction?("1 11/12").should be_false
198
- end
199
-
200
- it "should allow for negative denominators in single fractions" do
201
- Fractional.single_fraction?("1/-64").should be_true
202
- Fractional.single_fraction?("-1/-64").should be_true
203
- end
204
-
205
- end
206
-
207
- describe "Fractional", "mixed_fraction?" do
208
- it "should recognize a mixed fraction" do
209
- Fractional.mixed_fraction?("1 11/12").should be_true
210
- end
211
-
212
- it "should recognize a negative mixed fraciton" do
213
- Fractional.mixed_fraction?("-1 11/12").should be_true
214
- end
215
-
216
- it "should not recognize a single fraction" do
217
- Fractional.mixed_fraction?("3/4").should be_false
218
- end
219
- end