frac 0.9.2 → 0.9.3
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.
- data/README.rdoc +33 -0
- data/ext/frac_ext.c +3 -0
- data/lib/frac.rb +9 -4
- data/test/frac_test.rb +33 -0
- metadata +6 -4
data/README.rdoc
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
= Find rational approximation to given real number
|
2
|
+
|
3
|
+
Convert Float to Rational with given denominator maximum
|
4
|
+
|
5
|
+
Math.frac(0.2, 100) # => (1/5)
|
6
|
+
Math.frac(0.33, 10) # => (1/3)
|
7
|
+
Math.frac(0.33, 100) # => (33/100)
|
8
|
+
|
9
|
+
== Differe from ruby 1.9 build-in Float#to_r
|
10
|
+
|
11
|
+
# Build-in
|
12
|
+
1.1.to_r # => (2476979795053773/2251799813685248)
|
13
|
+
# Math#frac with big max denominator
|
14
|
+
Math.frac(1.1, 1_000_000_000) # => (11/10)
|
15
|
+
|
16
|
+
== Source
|
17
|
+
|
18
|
+
Idea and most implementation from http://www.ics.uci.edu/~eppstein/numth/frap.c
|
19
|
+
|
20
|
+
Based on the theory of continued fractions
|
21
|
+
|
22
|
+
if x = a1 + 1/(a2 + 1/(a3 + 1/(a4 + ...)))
|
23
|
+
|
24
|
+
then best approximation is found by truncating this series
|
25
|
+
(with some adjustments in the last term).
|
26
|
+
|
27
|
+
Note the fraction can be recovered as the first column of the matrix
|
28
|
+
|
29
|
+
( a1 1 ) ( a2 1 ) ( a3 1 ) ...
|
30
|
+
( 1 0 ) ( 1 0 ) ( 1 0 )
|
31
|
+
|
32
|
+
Instead of keeping the sequence of continued fraction terms,
|
33
|
+
we just keep the last partial product of these matrices.
|
data/ext/frac_ext.c
CHANGED
@@ -35,6 +35,9 @@ static VALUE find_fracs(VALUE mod, VALUE rv, VALUE dv)
|
|
35
35
|
double startx, x = RFLOAT_VALUE(rv);
|
36
36
|
long ai, maxden = NUM2LONG(dv);
|
37
37
|
|
38
|
+
if (maxden <= 0)
|
39
|
+
rb_raise(rb_eArgError, "maximum denominator should be > 0");
|
40
|
+
|
38
41
|
startx = x;
|
39
42
|
|
40
43
|
/* initialize matrix */
|
data/lib/frac.rb
CHANGED
@@ -1,10 +1,15 @@
|
|
1
1
|
|
2
|
+
require 'rational'
|
2
3
|
require 'frac_ext'
|
3
4
|
|
4
5
|
module Math
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
class << self
|
7
|
+
private :find_fracs
|
8
|
+
|
9
|
+
# Find rational approximation to given real number.
|
10
|
+
def frac(float, maxden)
|
11
|
+
arr = find_fracs(Float(float), Integer(maxden))
|
12
|
+
arr[2].abs > arr[5].abs ? Rational(arr[3], arr[4]) : Rational(arr[0], arr[1])
|
13
|
+
end
|
9
14
|
end
|
10
15
|
end
|
data/test/frac_test.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.join(File.dirname(__FILE__), %w{.. lib frac})
|
3
|
+
|
4
|
+
class TC_Frac < Test::Unit::TestCase
|
5
|
+
def test_frac
|
6
|
+
[[ 0.333, 1, 3, 0x100],
|
7
|
+
[ 0.77, 77, 100, 0x100],
|
8
|
+
[ 0.2, 1, 5, 0x100],
|
9
|
+
[ 2, 2, 1, 0x100],
|
10
|
+
[-0.5, -1, 2, 0x100],
|
11
|
+
[ 0, 0, 1, 0x100],
|
12
|
+
["0.85",17, 20, 0x100],
|
13
|
+
[ 0.5, 1, 2, '1000'],
|
14
|
+
[ 0.001, 0, 1, 2]
|
15
|
+
].each{|float, num, den, prec|
|
16
|
+
assert_equal Rational(num, den), Math.frac(float, prec), "#{float.inspect} -> #{num} / #{den}"
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_access
|
21
|
+
assert_raise NoMethodError do
|
22
|
+
Math.find_fracs 0.1, 0x100
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_validation
|
27
|
+
[[1.1, ''], [nil, 0x100], [1.1, 0], [1.5, -100]].each{|params|
|
28
|
+
assert_raise ArgumentError, TypeError do
|
29
|
+
Math.frac(*params)
|
30
|
+
end
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 9
|
8
|
-
-
|
9
|
-
version: 0.9.
|
8
|
+
- 3
|
9
|
+
version: 0.9.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Pavel Valodzka
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-05-
|
17
|
+
date: 2010-05-26 00:00:00 +03:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -30,6 +30,8 @@ files:
|
|
30
30
|
- ext/frac_ext.c
|
31
31
|
- ext/extconf.rb
|
32
32
|
- lib/frac.rb
|
33
|
+
- test/frac_test.rb
|
34
|
+
- README.rdoc
|
33
35
|
has_rdoc: true
|
34
36
|
homepage: http://github.com/valodzka/frac
|
35
37
|
licenses: []
|
@@ -59,6 +61,6 @@ rubyforge_project:
|
|
59
61
|
rubygems_version: 1.3.6
|
60
62
|
signing_key:
|
61
63
|
specification_version: 2
|
62
|
-
summary: Find rational approximation to given real number.
|
64
|
+
summary: Find rational approximation to given real number. Based on the theory of continued fractions if x = a1 + 1/(a2 + 1/(a3 + 1/(a4 + ...))) then best approximation is found by truncating this series (with some adjustments in the last term). Note the fraction can be recovered as the first column of the matrix ( a1 1 ) ( a2 1 ) ( a3 1 ) ... ( 1 0 ) ( 1 0 ) ( 1 0 ) Instead of keeping the sequence of continued fraction terms, we just keep the last partial product of these matrices.
|
63
65
|
test_files: []
|
64
66
|
|