frac 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source :rubygems
2
+
3
+ group :development, :test do
4
+ gem "rake"
5
+ gem "jeweler"
6
+ gem "rcov"
7
+ gem "rdoc"
8
+ gem "rake-compiler"
9
+ end
10
+
@@ -1,33 +1,52 @@
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.
1
+ = Find rational approximation to given real number
2
+
3
+ Convert Float or String to Fraction with given denominator maximum.
4
+
5
+ Math::Fraction.new(0.2) # => Fraction (1/5)
6
+ Math::Fraction.new("-3 1/8") # => Fraction (-3 1/8)
7
+
8
+ Math::Fraction.new(0.333) # => Fraction (1/3)
9
+ Math::Fraction.new("0.333") # => Fraction (1/3)
10
+ Math::Fraction.new(0.33, 100) # => Fraction (33/100)
11
+ Math::Fraction.new(1.to_f / 3) # => Fraction (1/3)
12
+
13
+ Math::Fraction.new(0.2).to_s # => String "1/5"
14
+ Math::Fraction.new(1.2).to_s # => String "1 1/5"
15
+ Math::Fraction.new(1.2).to_r # => Rational (6/5)
16
+ Math::Fraction.new(1.2).to_a # => Array [1, 1, 5]
17
+ Math::Fraction.new("0.333").to_a # => Array [0, 1, 3]
18
+
19
+ Math::Fraction.new(0.2, 100).to_r # => Rational (1/5)
20
+ Math::Fraction.new(0.33, 10).to_r # => Rational (1/3)
21
+ Math::Fraction.new(0.33, 100).to_r # => Rational (33/100)
22
+
23
+ == Difference from Ruby 1.9 built-in Float#to_r
24
+
25
+ # Built-in
26
+ 1.1.to_r # => (2476979795053773/2251799813685248)
27
+
28
+ # Math::Fraction with big max denominator
29
+ Math::Fraction.new(1.1, 1_000_000_000_000_000_000).to_r # => (11/10)
30
+
31
+ == Installation
32
+
33
+ gem install frac
34
+
35
+ == Source
36
+
37
+ Idea and most implementation from http://www.ics.uci.edu/~eppstein/numth/frap.c
38
+
39
+ Based on the theory of continued fractions
40
+
41
+ if x = a1 + 1/(a2 + 1/(a3 + 1/(a4 + ...)))
42
+
43
+ then best approximation is found by truncating this series
44
+ (with some adjustments in the last term).
45
+
46
+ Note the fraction can be recovered as the first column of the matrix
47
+
48
+ ( a1 1 ) ( a2 1 ) ( a3 1 ) ...
49
+ ( 1 0 ) ( 1 0 ) ( 1 0 )
50
+
51
+ Instead of keeping the sequence of continued fraction terms,
52
+ we just keep the last partial product of these matrices.
@@ -0,0 +1,77 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ gem.name = %q{frac}
17
+ gem.homepage = %q{https://github.com/valodzka/frac}
18
+ gem.license = %q{}
19
+ gem.summary = %q{Find rational approximation to given real number}
20
+ gem.email = %q{pavel@valodzka.name}
21
+ gem.authors = [%q{Pavel Valodzka}]
22
+ gem.extensions = ["ext/extconf.rb"]
23
+ gem.require_paths = ["lib"]
24
+ gem.summary = <<-RDOC
25
+ Find rational approximation to given real number.
26
+
27
+ Based on the theory of continued fractions
28
+
29
+ if x = a1 + 1/(a2 + 1/(a3 + 1/(a4 + ...)))
30
+
31
+ then best approximation is found by truncating this series
32
+ (with some adjustments in the last term).
33
+ Note the fraction can be recovered as the first column of the matrix
34
+
35
+ ( a1 1 ) ( a2 1 ) ( a3 1 ) ...
36
+ ( 1 0 ) ( 1 0 ) ( 1 0 )
37
+
38
+ Instead of keeping the sequence of continued fraction terms,
39
+ we just keep the last partial product of these matrices.
40
+ RDOC
41
+ end
42
+
43
+ require 'rake/extensiontask'
44
+ Rake::ExtensionTask.new do |ext|
45
+ ext.ext_dir = 'ext'
46
+ ext.lib_dir = 'lib'
47
+ ext.name = 'frac_ext'
48
+ end
49
+
50
+ Jeweler::RubygemsDotOrgTasks.new
51
+
52
+ require 'rake/testtask'
53
+ Rake::TestTask.new(:test) do |test|
54
+ test.libs << 'lib' << 'test'
55
+ test.pattern = 'test/**/*.rb'
56
+ test.verbose = true
57
+ end
58
+
59
+ require 'rcov/rcovtask'
60
+ Rcov::RcovTask.new do |test|
61
+ test.libs << 'test'
62
+ test.pattern = 'test/**/*.rb'
63
+ test.verbose = true
64
+ end
65
+
66
+ task :default => [ :compile, :test ]
67
+
68
+ require 'rdoc/task'
69
+ Rake::RDocTask.new do |rdoc|
70
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
71
+
72
+ rdoc.rdoc_dir = 'rdoc'
73
+ rdoc.title = "frac #{version}"
74
+ rdoc.rdoc_files.include('README*')
75
+ rdoc.rdoc_files.include('lib/**/*.rb')
76
+ end
77
+
data/VERSION ADDED
@@ -0,0 +1,2 @@
1
+ 0.9.4
2
+
@@ -1,4 +1,3 @@
1
-
2
1
  require 'mkmf'
3
2
 
4
3
  create_makefile("frac_ext")
@@ -1,90 +1,101 @@
1
- // http://www.ics.uci.edu/~eppstein/numth/frap.c
2
- /*
3
- ** find rational approximation to given real number
4
- ** David Eppstein / UC Irvine / 8 Aug 1993
5
- **
6
- ** With corrections from Arno Formella, May 2008
7
- **
8
- ** usage: a.out r d
9
- ** r is real number to approx
10
- ** d is the maximum denominator allowed
11
- **
12
- ** based on the theory of continued fractions
13
- ** if x = a1 + 1/(a2 + 1/(a3 + 1/(a4 + ...)))
14
- ** then best approximation is found by truncating this series
15
- ** (with some adjustments in the last term).
16
- **
17
- ** Note the fraction can be recovered as the first column of the matrix
18
- ** ( a1 1 ) ( a2 1 ) ( a3 1 ) ...
19
- ** ( 1 0 ) ( 1 0 ) ( 1 0 )
20
- ** Instead of keeping the sequence of continued fraction terms,
21
- ** we just keep the last partial product of these matrices.
22
- */
23
-
24
- #include <stdio.h>
25
- #include <ruby.h>
26
-
27
- #ifndef RFLOAT_VALUE
28
- # define RFLOAT_VALUE(v) RFLOAT(rb_Float(v))->value
29
- #endif
30
-
31
- static VALUE find_fracs(VALUE mod, VALUE rv, VALUE dv)
32
- {
33
- VALUE ret;
34
- long m[2][2];
35
- double startx, x = RFLOAT_VALUE(rv);
36
- long ai, maxden = NUM2LONG(dv);
37
-
38
- if (maxden <= 0)
39
- rb_raise(rb_eArgError, "maximum denominator should be > 0");
40
-
41
- startx = x;
42
-
43
- /* initialize matrix */
44
- m[0][0] = m[1][1] = 1;
45
- m[0][1] = m[1][0] = 0;
46
-
47
- /* loop finding terms until denom gets too big */
48
- while (m[1][0] * ( ai = (long)x ) + m[1][1] <= maxden) {
49
- long t;
50
- t = m[0][0] * ai + m[0][1];
51
- m[0][1] = m[0][0];
52
- m[0][0] = t;
53
- t = m[1][0] * ai + m[1][1];
54
- m[1][1] = m[1][0];
55
- m[1][0] = t;
56
- if(x==(double)ai) break; // AF: division by zero
57
- x = 1/(x - (double) ai);
58
- if(x>(double)0x7FFFFFFF) break; // AF: representation failure
59
- }
60
-
61
- {
62
- /* now remaining x is between 0 and 1/ai */
63
- /* approx as either 0 or 1/m where m is max that will fit in maxden */
64
- /* first try zero */
65
- VALUE num1, den1, err1, num2, den2, err2;
66
-
67
- num1 = LONG2NUM(m[0][0]);
68
- den1 = LONG2NUM(m[1][0]);
69
- err1 = rb_float_new(startx - ((double) m[0][0] / (double) m[1][0]));
70
-
71
- /* now try other possibility */
72
- ai = (maxden - m[1][1]) / m[1][0];
73
- m[0][0] = m[0][0] * ai + m[0][1];
74
- m[1][0] = m[1][0] * ai + m[1][1];
75
-
76
- num2 = LONG2NUM(m[0][0]);
77
- den2 = LONG2NUM(m[1][0]);
78
- err2 = rb_float_new(startx - ((double) m[0][0] / (double) m[1][0]));
79
-
80
- return rb_ary_new3(6, num1, den1, err1, num2, den2, err2);
81
- }
82
- }
83
-
84
-
85
- void Init_frac_ext()
86
- {
87
- rb_define_module_function(rb_mMath, "find_fracs", find_fracs, 2);
88
- }
89
-
90
-
1
+ /*
2
+ ** find rational approximation to given real number
3
+ ** David Eppstein / UC Irvine / 8 Aug 1993
4
+ **
5
+ ** With corrections from Arno Formella, May 2008
6
+ **
7
+ ** usage: a.out r d
8
+ ** r is real number to approx
9
+ ** d is the maximum denominator allowed
10
+ **
11
+ ** based on the theory of continued fractions
12
+ ** if x = a1 + 1/(a2 + 1/(a3 + 1/(a4 + ...)))
13
+ ** then best approximation is found by truncating this series
14
+ ** (with some adjustments in the last term).
15
+ **
16
+ ** Note the fraction can be recovered as the first column of the matrix
17
+ ** ( a1 1 ) ( a2 1 ) ( a3 1 ) ...
18
+ ** ( 1 0 ) ( 1 0 ) ( 1 0 )
19
+ ** Instead of keeping the sequence of continued fraction terms,
20
+ ** we just keep the last partial product of these matrices.
21
+ */
22
+
23
+ #include <stdio.h>
24
+ #include <ruby.h>
25
+
26
+ #ifndef RFLOAT_VALUE
27
+ # define RFLOAT_VALUE(v) RFLOAT(rb_Float(v))->value
28
+ #endif
29
+
30
+ #ifdef HAVE_LONG_LONG
31
+ # define N_TYPE LONG_LONG
32
+ # define R2N NUM2LL
33
+ # define N2R LL2NUM
34
+ #else
35
+ # define N_TYPE long
36
+ # define R2N NUM2LONG
37
+ # define N2R LONG2NUM
38
+ #endif
39
+
40
+ static VALUE find_fracs(VALUE mod, VALUE rv, VALUE dv)
41
+ {
42
+ VALUE ret;
43
+ N_TYPE m[2][2], ai, maxden = R2N(rb_Integer(dv));
44
+ double startx, x = RFLOAT_VALUE(rb_Float(rv));
45
+ int sign = 1;
46
+
47
+ if (maxden <= 0)
48
+ rb_raise(rb_eArgError, "maximum denominator should be > 0");
49
+
50
+ if (x < 0) {
51
+ sign = -1;
52
+ x = -x;
53
+ }
54
+
55
+ startx = x;
56
+
57
+ /* initialize matrix */
58
+ m[0][0] = m[1][1] = 1;
59
+ m[0][1] = m[1][0] = 0;
60
+
61
+ /* loop finding terms until denom gets too big */
62
+ while (m[1][0] * ( ai = (N_TYPE)x ) + m[1][1] <= maxden) {
63
+ N_TYPE t;
64
+ t = m[0][0] * ai + m[0][1];
65
+ m[0][1] = m[0][0];
66
+ m[0][0] = t;
67
+ t = m[1][0] * ai + m[1][1];
68
+ m[1][1] = m[1][0];
69
+ m[1][0] = t;
70
+ if(x==(double)ai) break; // AF: division by zero
71
+ x = 1/(x - (double) ai);
72
+ if(x>(double)0x7FFFFFFF) break; // AF: representation failure
73
+ }
74
+
75
+ {
76
+ /* now remaining x is between 0 and 1/ai */
77
+ /* approx as either 0 or 1/m where m is max that will fit in maxden */
78
+ /* first try zero */
79
+ VALUE num1, den1, err1, num2, den2, err2;
80
+
81
+ num1 = N2R(sign*m[0][0]);
82
+ den1 = N2R(m[1][0]);
83
+ err1 = rb_float_new(startx - ((double) m[0][0] / (double) m[1][0]));
84
+
85
+ /* now try other possibility */
86
+ ai = (maxden - m[1][1]) / m[1][0];
87
+ m[0][0] = m[0][0] * ai + m[0][1];
88
+ m[1][0] = m[1][0] * ai + m[1][1];
89
+
90
+ num2 = N2R(sign*m[0][0]);
91
+ den2 = N2R(m[1][0]);
92
+ err2 = rb_float_new(startx - ((double) m[0][0] / (double) m[1][0]));
93
+
94
+ return rb_ary_new3(6, num1, den1, err1, num2, den2, err2);
95
+ }
96
+ }
97
+
98
+ void Init_frac_ext()
99
+ {
100
+ rb_define_module_function(rb_mMath, "find_fracs", find_fracs, 2);
101
+ }
@@ -0,0 +1,53 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{frac}
8
+ s.version = "0.9.3"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Pavel Valodzka"]
12
+ s.date = %q{2011-06-19}
13
+ s.email = %q{pavel@valodzka.name}
14
+ s.extensions = ["ext/extconf.rb"]
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ "README.rdoc",
20
+ "VERSION",
21
+ "ext/extconf.rb",
22
+ "ext/frac_ext.c",
23
+ "frac.gemspec",
24
+ "lib/frac.js",
25
+ "lib/frac.rb",
26
+ "test/frac_test.html",
27
+ "test/frac_test.rb"
28
+ ]
29
+ s.homepage = %q{https://github.com/valodzka/frac}
30
+ s.licenses = [""]
31
+ s.require_paths = ["lib"]
32
+ s.rubygems_version = %q{1.6.2}
33
+ s.summary = %q{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.}
34
+
35
+ if s.respond_to? :specification_version then
36
+ s.specification_version = 3
37
+
38
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
39
+ s.add_development_dependency(%q<rake>, [">= 0"])
40
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
41
+ s.add_development_dependency(%q<rcov>, [">= 0"])
42
+ else
43
+ s.add_dependency(%q<rake>, [">= 0"])
44
+ s.add_dependency(%q<jeweler>, [">= 0"])
45
+ s.add_dependency(%q<rcov>, [">= 0"])
46
+ end
47
+ else
48
+ s.add_dependency(%q<rake>, [">= 0"])
49
+ s.add_dependency(%q<jeweler>, [">= 0"])
50
+ s.add_dependency(%q<rcov>, [">= 0"])
51
+ end
52
+ end
53
+
@@ -0,0 +1,41 @@
1
+
2
+ (function(){
3
+ var find_fracs = function(x, maxden) {
4
+ var startx = x, ai;
5
+ var m = [[1.0, 0.0],[0.0, 1.0]];
6
+
7
+ if (maxden <= 0)
8
+ throw "Max denominator should be greater then 0";
9
+
10
+ while (m[1][0] * (ai = parseInt(x)) + m[1][1] <= maxden) {
11
+ var t = m[0][0] * ai + m[0][1];
12
+ m[0][1] = m[0][0];
13
+ m[0][0] = t;
14
+ t = m[1][0] * ai + m[1][1];
15
+ m[1][1] = m[1][0];
16
+ m[1][0] = t;
17
+ if (x == ai) break; /* AF: division by zero */
18
+ x = 1/(x - ai);
19
+ if (x > 0x7FFFFFFF) break /* AF: representation failure */
20
+ }
21
+
22
+ var num1 = m[0][0];
23
+ var den1 = m[1][0];
24
+ var err1 = startx - num1 / den1;
25
+
26
+ ai = (maxden - m[1][1]) / m[1][0];
27
+ m[0][0] = m[0][0] * ai + m[0][1];
28
+ m[1][0] = m[1][0] * ai + m[1][1];
29
+
30
+ var num2 = m[0][0];
31
+ var den2 = m[1][0];
32
+ var err2 = startx - num2 / den2;
33
+
34
+ return [err1, [num1, den1], err2, [num2, den2]];
35
+ };
36
+
37
+ Math["frac"] = function(x, maxden) {
38
+ var fracs = find_fracs(parseFloat(x), parseInt(maxden));
39
+ return Math.abs(fracs[0]) < Math.abs(fracs[2]) ? fracs[1] : fracs[3];
40
+ };
41
+ })();
@@ -1,15 +1,62 @@
1
-
2
- require 'rational'
3
- require 'frac_ext'
4
-
5
- module Math
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
14
- end
15
- end
1
+ require 'rational'
2
+ require File.join(File.dirname(__FILE__), %w{.. lib frac_ext})
3
+
4
+ # Rational approximation to given real number.
5
+ module Math
6
+
7
+ class << self
8
+ private :find_fracs
9
+
10
+ def frac(float, maxden)
11
+ arr = find_fracs(float, maxden)
12
+ arr[2].abs > arr[5].abs ? Rational(arr[3], arr[4]) : Rational(arr[0], arr[1])
13
+ end
14
+ end
15
+
16
+ class Fraction
17
+
18
+ def initialize(float, maxden = 0x100)
19
+ if float.is_a?(String)
20
+ @r = 0
21
+ sign = 1
22
+ float.split(' ', 2).each do |part|
23
+ if (part.include?("/"))
24
+ @r += sign * Rational(*(part.split('/', 2).map(&method(:Integer))))
25
+ else
26
+ @r += Math.frac(part, maxden)
27
+ sign = @r >= 0 ? 1 : -1
28
+ end
29
+ end
30
+ else
31
+ @r = Math.frac(float, maxden)
32
+ end
33
+ end
34
+
35
+ def to_a
36
+ i = @r.to_i
37
+ sign = i >= 0 ? 1 : -1
38
+ [ i, (@r.numerator - i * @r.denominator) * sign, @r.denominator ]
39
+ end
40
+
41
+ def to_r
42
+ @r
43
+ end
44
+
45
+ def to_f
46
+ @r.to_f
47
+ end
48
+
49
+ def to_s
50
+ n = to_a
51
+ if n[1] == 0
52
+ n[0].to_s
53
+ elsif n[0] == 0
54
+ "#{n[1]}/#{n[2]}"
55
+ else
56
+ "#{n[0]} #{n[1]}/#{n[2]}"
57
+ end
58
+ end
59
+
60
+ end
61
+ end
62
+
@@ -0,0 +1,39 @@
1
+
2
+ <script src="../lib/frac.js" type="text/javascript"></script>
3
+
4
+ <script>
5
+ function msg(str) {
6
+ document.write(str);
7
+ };
8
+
9
+ function err(str) {
10
+ msg("<p style='color:red;'>"+str+"</p>");
11
+ };
12
+
13
+ function ok(str) {
14
+ msg("<p style='color:green'>"+str+"</p>");
15
+ };
16
+
17
+ function assert(expected, result, msg) {
18
+ if (expected != result && expected.toString() != result.toString())
19
+ err("Error, expected " + expected + ", got " + result + ": " + msg);
20
+ else
21
+ ok("OK: " + msg);
22
+ };
23
+
24
+ var tests = [
25
+ [ 0.333,[ 1, 3], 0x100],
26
+ [ 0.77, [77, 100], 0x100],
27
+ [ 0.2, [ 1, 5], 0x100],
28
+ [ 2, [ 2, 1], 0x100],
29
+ [-0.5, [-1, 2], 0x100],
30
+ [ 0, [ 0, 1], 0x100],
31
+ ["0.85",[17, 20], 0x100],
32
+ [ 0.5, [ 1, 2], '1000'],
33
+ [ 0.001,[ 0, 1], 2]];
34
+
35
+ for (var i = 0; i < tests.length; ++i) {
36
+ var sample = tests[i];
37
+ assert(sample[1], Math.frac(sample[0], sample[2]), sample[0] + " -> " + sample[1][0] + " / " + sample[1][1]);
38
+ }
39
+ </script>
@@ -3,17 +3,40 @@ require File.join(File.dirname(__FILE__), %w{.. lib frac})
3
3
 
4
4
  class TC_Frac < Test::Unit::TestCase
5
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}"
6
+ [[ 0.333, [1, 3], 0x100, [0, 1, 3], "1/3" ],
7
+ [ 1.to_f/3, [1, 3], 0x100, [0, 1, 3], "1/3" ],
8
+ [ 0.77, [77, 100], 0x100, [0, 77, 100], "77/100" ],
9
+ [ 0.2, [1, 5], 0x100, [0, 1, 5], "1/5" ],
10
+ [ 2, [2, 1], 0x100, [2, 0, 1], "2" ],
11
+ [-0.5, [-1, 2], 0x100, [0, -1, 2], "-1/2" ],
12
+ [-1.5, [-3, 2], 0x100, [-1, 1, 2], "-1 1/2" ],
13
+ [-1.7, [-17, 10], 0x100, [-1, 7, 10], "-1 7/10" ],
14
+ [-2.7, [-27, 10], 10, [-2, 7, 10], "-2 7/10" ],
15
+ [ 0, [0, 1], 0x100, [0, 0, 1], "0" ],
16
+ [ 0.85, [17, 20], 0x100, [0, 17, 20], "17/20" ],
17
+ [ 0.5, [1, 2], '1000', [0, 1, 2], "1/2" ],
18
+ [ 0.001, [0, 1], 2, [0, 0, 1], "0" ],
19
+ [ 0.001, [1, 1000], 1000, [0, 1, 1000], "1/1000" ],
20
+ [ 3.56, [89, 25], 0x100, [3, 14, 25], "3 14/25" ],
21
+ [ "3.56", [89, 25], 0x100, [3, 14, 25], "3 14/25" ],
22
+ ].each{|float, num_den, prec, n, s|
23
+ assert_equal Rational(num_den[0], num_den[1]), Math.frac(float, prec), "#{float.inspect} -> #{num_den[0]} / #{num_den[1]}"
24
+ assert_equal n, Math::Fraction.new(float, prec).to_a, "#{float.inspect} -> #{n}"
25
+ assert_equal s, Math::Fraction.new(float, prec).to_s, "#{float.inspect} -> #{s}"
26
+ }
27
+ end
28
+
29
+ def test_frac_strings
30
+ [[ "0.333", [0, 1, 3], "1/3", 1.to_f / 3 ],
31
+ [ "3.56", [3, 14, 25], "3 14/25", 3.56 ],
32
+ [ "3 1/8", [3, 1, 8], "3 1/8", 3.125 ],
33
+ [ "-3 1/8", [-3, 1, 8], "-3 1/8", -3.125 ],
34
+ [ "-1/8", [0, -1, 8], "-1/8", -0.125 ],
35
+ ].each{|float, n, s, f|
36
+ r = Math::Fraction.new(float)
37
+ assert_equal n, r.to_a, "#{float.inspect} -> #{n}"
38
+ assert_equal s, r.to_s, "#{float.inspect} -> #{s}"
39
+ assert_equal f, r.to_f, "#{float.inspect} -> #{f}"
17
40
  }
18
41
  end
19
42
 
@@ -23,11 +46,19 @@ class TC_Frac < Test::Unit::TestCase
23
46
  end
24
47
  end
25
48
 
26
- def test_validation
49
+ def test_frac_validation
27
50
  [[1.1, ''], [nil, 0x100], [1.1, 0], [1.5, -100]].each{|params|
28
51
  assert_raise ArgumentError, TypeError do
29
52
  Math.frac(*params)
30
53
  end
31
54
  }
32
55
  end
56
+
57
+ def test_fractions_validation
58
+ ['junk', 'junk 2/3', '10 junk/2', '11 3/junk', nil].each{|param|
59
+ assert_raise ArgumentError, TypeError, "For param #{param}" do
60
+ Math::Fraction.new(param)
61
+ end
62
+ }
63
+ end
33
64
  end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: frac
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 51
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 9
8
- - 3
9
- version: 0.9.3
9
+ - 4
10
+ version: 0.9.4
10
11
  platform: ruby
11
12
  authors:
12
13
  - Pavel Valodzka
@@ -14,53 +15,132 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-05-26 00:00:00 +03:00
18
+ date: 2011-06-24 00:00:00 +03:00
18
19
  default_executable:
19
- dependencies: []
20
-
21
- description: Find rational approximation to given real number
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ prerelease: false
23
+ type: :development
24
+ name: rake
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ requirement: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ prerelease: false
37
+ type: :development
38
+ name: jeweler
39
+ version_requirements: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ requirement: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ prerelease: false
51
+ type: :development
52
+ name: rcov
53
+ version_requirements: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ requirement: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ prerelease: false
65
+ type: :development
66
+ name: rdoc
67
+ version_requirements: &id004 !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 3
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ requirement: *id004
77
+ - !ruby/object:Gem::Dependency
78
+ prerelease: false
79
+ type: :development
80
+ name: rake-compiler
81
+ version_requirements: &id005 !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ requirement: *id005
91
+ description:
22
92
  email: pavel@valodzka.name
23
93
  executables: []
24
94
 
25
95
  extensions:
26
96
  - ext/extconf.rb
27
- extra_rdoc_files: []
28
-
97
+ extra_rdoc_files:
98
+ - README.rdoc
29
99
  files:
30
- - ext/frac_ext.c
100
+ - Gemfile
101
+ - README.rdoc
102
+ - Rakefile
103
+ - VERSION
31
104
  - ext/extconf.rb
105
+ - ext/frac_ext.c
106
+ - frac.gemspec
107
+ - lib/frac.js
32
108
  - lib/frac.rb
109
+ - test/frac_test.html
33
110
  - test/frac_test.rb
34
- - README.rdoc
35
111
  has_rdoc: true
36
- homepage: http://github.com/valodzka/frac
37
- licenses: []
38
-
112
+ homepage: https://github.com/valodzka/frac
113
+ licenses:
114
+ - ""
39
115
  post_install_message:
40
116
  rdoc_options: []
41
117
 
42
118
  require_paths:
43
119
  - lib
44
120
  required_ruby_version: !ruby/object:Gem::Requirement
121
+ none: false
45
122
  requirements:
46
123
  - - ">="
47
124
  - !ruby/object:Gem::Version
125
+ hash: 3
48
126
  segments:
49
127
  - 0
50
128
  version: "0"
51
129
  required_rubygems_version: !ruby/object:Gem::Requirement
130
+ none: false
52
131
  requirements:
53
132
  - - ">="
54
133
  - !ruby/object:Gem::Version
134
+ hash: 3
55
135
  segments:
56
136
  - 0
57
137
  version: "0"
58
138
  requirements: []
59
139
 
60
140
  rubyforge_project:
61
- rubygems_version: 1.3.6
141
+ rubygems_version: 1.3.7
62
142
  signing_key:
63
- specification_version: 2
143
+ specification_version: 3
64
144
  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.
65
145
  test_files: []
66
146