frac 0.9.3 → 0.9.4

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/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