oILAB
Loading...
Searching...
No Matches
BestRationalApproximation.h
Go to the documentation of this file.
1/* This file is part of gbLAB.
2 *
3 * gbLAB is distributed without any warranty under the MIT License.
4 */
5
6
7#ifndef gbLAB_BESTRATIONALAPPROXIMATION_H_
8#define gbLAB_BESTRATIONALAPPROXIMATION_H_
9
10#include <math.h>
11
12// https://rosettacode.org/wiki/Convert_decimal_number_to_rational#C
13
14namespace gbLAB
15{
16
18 {
19 public:
20 //typedef int64_t LongIntType;
21 typedef long long int LongIntType;
22
23 private:
24 static std::pair<LongIntType,LongIntType> rat_approx(double f, LongIntType md)
25 {
26 if(fabs(f)<1.0/md)
27 {
28 return std::pair<LongIntType,LongIntType>(0,1);
29 }
30
31
32 /* a: continued fraction coefficients. */
33 LongIntType a, h[3] = { 0, 1, 0 }, k[3] = { 1, 0, 0 };
34 LongIntType x, d, n = 1;
35 long int i, neg = 0;
36
37 if (md <= 1)
38 { // *denom = 1; *num = (LongIntType) f; return;
39 return std::pair<LongIntType,LongIntType>(f,1);
40 }
41
42 if (f < 0.0)
43 {
44 neg = 1;
45 f = -f;
46 }
47
48
49 while (f != floor(f))
50 {
51 n <<= 1;
52 f *= 2;
53 }
54
55 d = f;
56
57
58 /* continued fraction and check denominator each step */
59 for (i = 0; i < 64; i++)
60 {
61
62 a = n ? d / n : 0;
63 if (i && !a) break;
64
65 x = d;
66 d = n;
67
68
69 n = x % n;
70
71 x = a;
72 if (k[1] * a + k[0] >= md)
73 {
74 x = (md - k[0]) / k[1];
75 if (x * 2 >= a || k[1] >= md)
76 i = 65;
77 else
78 break;
79 }
80
81 h[2] = x * h[1] + h[0]; h[0] = h[1]; h[1] = h[2];
82 k[2] = x * k[1] + k[0]; k[0] = k[1]; k[1] = k[2];
83 }
84 return std::pair<LongIntType,LongIntType>(neg ? -h[1] : h[1],k[1]);
85 }
86
87 const std::pair<LongIntType,LongIntType> intPair;
88
89 public:
90
93
94 BestRationalApproximation(const double& f, const LongIntType& md) :
95 /* init list */ intPair(isfinite(f)? rat_approx(f,md) : std::pair<LongIntType,LongIntType>(1,0)),
96 /* init list */ num(intPair.first),
97 /* init list */ den(intPair.second)
98 {
99
100 }
101
102 };
103
104}
105#endif
static std::pair< LongIntType, LongIntType > rat_approx(double f, LongIntType md)
BestRationalApproximation(const double &f, const LongIntType &md)
const std::pair< LongIntType, LongIntType > intPair