fraction 0.1
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/extconf.rb +5 -0
- data/fraction.c +105 -0
- metadata +57 -0
data/extconf.rb
ADDED
data/fraction.c
ADDED
@@ -0,0 +1,105 @@
|
|
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
|
+
** Made into a ruby module by Christopher Lord, Nov 2009
|
8
|
+
**
|
9
|
+
** usage: require 'findfract'
|
10
|
+
**
|
11
|
+
** n,d,err = 0.33.fraction
|
12
|
+
**
|
13
|
+
** based on the theory of continued fractions
|
14
|
+
** if x = a1 + 1/(a2 + 1/(a3 + 1/(a4 + ...)))
|
15
|
+
** then best approximation is found by truncating this series
|
16
|
+
** (with some adjustments in the last term).
|
17
|
+
**
|
18
|
+
** Note the fraction can be recovered as the first column of the matrix
|
19
|
+
** ( a1 1 ) ( a2 1 ) ( a3 1 ) ...
|
20
|
+
** ( 1 0 ) ( 1 0 ) ( 1 0 )
|
21
|
+
** Instead of keeping the sequence of continued fraction terms,
|
22
|
+
** we just keep the last partial product of these matrices.
|
23
|
+
*/
|
24
|
+
|
25
|
+
#include "ruby.h"
|
26
|
+
#include <stdio.h>
|
27
|
+
VALUE method_html_form_for(VALUE self)
|
28
|
+
{
|
29
|
+
VALUE res = rb_str_new2("<span class='fraction'><span class='above'>");
|
30
|
+
// This is an array. to make a string form, we want to
|
31
|
+
VALUE num = rb_obj_as_string(rb_ary_entry(self, 0));
|
32
|
+
VALUE den = rb_obj_as_string(rb_ary_entry(self, 1));
|
33
|
+
rb_str_concat(res, rb_obj_as_string(num));
|
34
|
+
rb_str_cat2(res, "</span>⁄<span class='below'>");
|
35
|
+
rb_str_concat(res, rb_obj_as_string(den));
|
36
|
+
rb_str_cat2(res, "</span></span>");
|
37
|
+
// CSS for the above html (From http://www.cs.tut.fi/~jkorpela/math/#fractions)
|
38
|
+
// .above, .below { font-size: 70%;
|
39
|
+
// font-family: Verdana, Arial, sans-serif; }
|
40
|
+
// .above { vertical-align: 0.7ex; }
|
41
|
+
// .below { vertical-align: -0.3ex; }
|
42
|
+
return res;
|
43
|
+
}
|
44
|
+
VALUE method_string_form_for(VALUE self)
|
45
|
+
{
|
46
|
+
VALUE res = rb_str_new2("");
|
47
|
+
// This is an array. to make a string form, we want to
|
48
|
+
VALUE num = rb_obj_as_string(rb_ary_entry(self, 0));
|
49
|
+
VALUE den = rb_obj_as_string(rb_ary_entry(self, 1));
|
50
|
+
rb_str_concat(res, rb_obj_as_string(num));
|
51
|
+
rb_str_cat2(res, "/");
|
52
|
+
rb_str_concat(res, rb_obj_as_string(den));
|
53
|
+
return res;
|
54
|
+
}
|
55
|
+
VALUE method_fraction_for(int argc, VALUE * argv, VALUE self)
|
56
|
+
{
|
57
|
+
long m11, m12,
|
58
|
+
m21, m22;
|
59
|
+
VALUE res = rb_ary_new2(3);
|
60
|
+
VALUE maxdenr;
|
61
|
+
int maxden = 10; // the default
|
62
|
+
rb_scan_args(argc, argv, "01", &maxdenr);
|
63
|
+
if (!NIL_P(maxdenr))
|
64
|
+
maxden = NUM2INT(maxdenr);
|
65
|
+
int ai;
|
66
|
+
double x = NUM2DBL(self);
|
67
|
+
double startx = x;
|
68
|
+
m11 = m22 = 1;
|
69
|
+
m12 = m21 = 0;
|
70
|
+
|
71
|
+
// loop finding terms until denom gets too big
|
72
|
+
while (m21 * ( ai = (long)x ) + m22 <= maxden) {
|
73
|
+
long t = m11 * ai + m12;
|
74
|
+
m12 = m11;
|
75
|
+
m11 = t;
|
76
|
+
t = m21 * ai + m22;
|
77
|
+
m22 = m21;
|
78
|
+
m21 = t;
|
79
|
+
if(x==(double)ai) break;
|
80
|
+
x = 1/(x - (double) ai);
|
81
|
+
if(x>(double)0x7FFFFFFF) break;
|
82
|
+
}
|
83
|
+
VALUE numer1 = INT2NUM(m11);
|
84
|
+
VALUE denom1 = INT2NUM(m21);
|
85
|
+
VALUE err1 = rb_float_new(startx - ((double) m11 / (double) m21));
|
86
|
+
rb_ary_store(res, 0, numer1);
|
87
|
+
rb_ary_store(res, 1, denom1);
|
88
|
+
rb_ary_store(res, 2, err1);
|
89
|
+
// rb_define_singleton_method(res, "to_s", method_string_form_for, 0);
|
90
|
+
// rb_define_singleton_method(res, "to_html", method_html_form_for, 0);
|
91
|
+
|
92
|
+
|
93
|
+
/* We can go one more step to find another candidate:
|
94
|
+
m11 = m11 * ai + m12;
|
95
|
+
m21 = m21 * ai + m22;
|
96
|
+
m11/m21, err= startx - ((double) m11 / (double) m21))
|
97
|
+
*/
|
98
|
+
return res;
|
99
|
+
}
|
100
|
+
|
101
|
+
void Init_fraction() {
|
102
|
+
rb_define_method(rb_cNumeric, "fraction", method_fraction_for, -1);
|
103
|
+
rb_define_method(rb_cFloat, "fraction", method_fraction_for, -1);
|
104
|
+
}
|
105
|
+
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fraction
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Christopher Lord
|
8
|
+
- David Eppstein
|
9
|
+
- Arno Formella
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
|
14
|
+
date: 2009-11-27 00:00:00 -05:00
|
15
|
+
default_executable:
|
16
|
+
dependencies: []
|
17
|
+
|
18
|
+
description: Provides a "fraction" method on all ruby floats.
|
19
|
+
email: christopherlord+fractiongem@gmail.com
|
20
|
+
executables: []
|
21
|
+
|
22
|
+
extensions:
|
23
|
+
- extconf.rb
|
24
|
+
extra_rdoc_files: []
|
25
|
+
|
26
|
+
files:
|
27
|
+
- fraction.c
|
28
|
+
has_rdoc: true
|
29
|
+
homepage: http://christopher.lord.ac
|
30
|
+
licenses: []
|
31
|
+
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
|
35
|
+
require_paths:
|
36
|
+
- lib
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: "0"
|
42
|
+
version:
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: "0"
|
48
|
+
version:
|
49
|
+
requirements: []
|
50
|
+
|
51
|
+
rubyforge_project:
|
52
|
+
rubygems_version: 1.3.5
|
53
|
+
signing_key:
|
54
|
+
specification_version: 3
|
55
|
+
summary: Provides a "fraction" method on all ruby floats.
|
56
|
+
test_files: []
|
57
|
+
|