рдХрдореНрдкреНрдпреВрдЯрд┐рдВрдЧ рдлреНрд▓реЛрдЯрд┐рдВрдЧ рдкреЙрдЗрдВрдЯ рдЧрдгрдирд╛

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ, рд╕реА ++ рдореЗрдВ рдЖрдк рд╕рдВрдХрд▓рди рдЪрд░рдг рдореЗрдВ рдЬрдЯрд┐рд▓ рдлреНрд▓реЛрдЯрд┐рдВрдЧ-рдкреЙрдЗрдВрдЯ рдЧрдгрдирд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдореИрдВрдиреЗ рдЗрд╕ рдХрд╖реНрдЯрдкреНрд░рдж рджреЛрд╖ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рд╣рдо рдЬрд┐рд╕ рд▓рдХреНрд╖реНрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ рд╡рд╣ рд░реВрдЯ рдХреА рдЧрдгрдирд╛ рдХрд╛ рдЙрджрд╛рд╣рд░рдг рд╣реИ:
typedef RATIONAL(2,0) x; typedef sqrt<x>::type result; 

рд╕рдВрдЦреНрдпрд╛ рдХреА рдЬрдбрд╝ рдХреА рдЧрдгрдирд╛ рд╕рдВрдХрд▓рди рдЪрд░рдг рдореЗрдВ рдХреА рдЬрд╛рддреА рд╣реИред рд╕рдВрдЦреНрдпрд╛ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рджреЛ рдкреВрд░реНрдгрд╛рдВрдХреЛрдВ рдХреЗ рдЕрдиреБрдкрд╛рдд рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореВрд▓реНрдп рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдкреНрд░рд╛рдкреНрдд () рд╡рд┐рдзрд┐ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкрд╣реБрдВрдЪрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ;
 std::cout << result::get() << std::endl; 
1.41421356

рдлреНрд▓реЛрдЯрд┐рдВрдЧ рдкреЙрдЗрдВрдЯ рдирдВрдмрд░реЛрдВ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕рдВрдмрдВрдз рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ
рджреЛ рдкреВрд░реНрдгрд╛рдВрдХ - рдПрдХ рдЕрдВрд╢ред
 template <int64_t A, int64_t B> struct rational_t { const static int64_t a = A, b = B; static double get() { return (double)a/b; } }; 

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕рдВрдЦреНрдпрд╛ 2 рдХреЛ рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЯрд╛рдЗрдк рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ rational_t тАЛтАЛ<2,1> (рдкрд╣рд▓реЗ рджреЛ)
 rational_t<3,2> -> 3/2 rational_t<56,10> -> 56/10 = 5.6 rational_t<3,100> -> 3/100 = 0.03 

рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЪрд╛рд▓рд╛рдХ рд░рд╛рд╖реНрдЯреНрд░реАрдп рдореИрдХреНрд░реЛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ:
 #define RATIONAL(A1, A2) rational_t<(int)(A1##A2), pow<10, sizeof(#A2)-1>::value> 

рдЗрд╕реЗ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдиреЗрдВ: рд░рд╛рд╖реНрдЯреНрд░реАрдп (12.34) - 12.34 (12 рдЕрдВрдХ 34 рд╕реМрд╡рд╛рдВ рднрд╛рдЧ) рдШреЛрд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ
 1) A1 ## A2 1234 рдореЗрдВ рджреЛ рддрд░реНрдХ рджреЗрддрд╛ рд╣реИ
 2) рдЖрдХрд╛рд░ (# A2) -1 = рдЖрдХрд╛рд░ ("34") - 1 = 3 - 1 = 2
 3) рдкрд╛рдЙ <10, 2> :: рдореВрд▓реНрдп = 10 рд╕реЗ 2 = 100 рдХреА рд╢рдХреНрддрд┐

рдЗрд╕ рдкреНрд░рдХрд╛рд░, RATIONAL (12.34) рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЛ рддрд░реНрдХрд╕рдВрдЧрдд_t рдШреЛрд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ <1234, 100> (рдЕрд░реНрдерд╛рдд 1234/100 = 12.34)
рдкрд╛рд╡ рдлрд╝рдВрдХреНрд╢рди рдЗрд╕ рддрд░рд╣ рд▓рд┐рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ:
 template <int V, unsigned D> struct pow { const static int value = V * pow<V, D - 1>::value; }; template <int V> struct pow<V, 0> { const static int value = 1; }; 

рд╣рдо рддрд░реНрдХрд╕рдВрдЧрдд_рдЯ рдкреИрдЯрд░реНрди рдХреЗ рд▓рд┐рдП рдЕрдВрдХрдЧрдгрд┐рддреАрдп рд╕рдВрдЪрд╛рд▓рди рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВред
рдЕрдВрд╢реЛрдВ рдХрд╛ рдЬреЛрдбрд╝: a1 / b1 + a2 / b2 = (a1 * b2 + a2 * b1) / (b1 * b2), рдЗрд╕рд▓рд┐рдП:
 template <class R1, class R2> struct plus { typedef rational_t<R1::a * R2::b + R2::a * R1::b, R1::b * R2::b> type; }; 

рдирд┐рд░рдВрддрд░ рдЬреЛрдбрд╝ рдХреЗ рд╕рд╛рде, рдЕрдВрд╢ рдФрд░ рд╣рд░ рд▓рдЧрд╛рддрд╛рд░ рдирд┐рд░рдкреЗрдХреНрд╖ рдореВрд▓реНрдп рдореЗрдВ рдмрдврд╝реЗрдЧрд╛ред рдЕрдЧрд▓реЗ рдЬреЛрдбрд╝ рдХреЗ рджреМрд░рд╛рди рдЕрддрд┐рдкреНрд░рд╡рд╛рд╣ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП, рдЕрдВрд╢ рдХреЛ рдХрдо рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рд╣рдо рдЕрддрд┐рд░рд┐рдХреНрдд рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрддреЗ рд╣реИрдВ:
 template <class R1, class R2> struct plus { typedef rational_t<R1::a * R2::b + R2::a * R1::b, R1::b * R2::b> type1; typedef typename reduce<type1>::type type; }; 

рдХрдо рдореЗрдЯрд╛ рдлрд╝рдВрдХреНрд╢рди рдПрдХ рдЕрд╕реНрдкрд╖реНрдЯ рдЕрдВрд╢ рд▓реЗрддрд╛ рд╣реИ рдФрд░ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд░реВрдк рджреЗрддрд╛ рд╣реИред рдпрд╣рд╛рдВ рд╢реЗрд╖ рд╕рдВрдЪрд╛рд▓рди рд╣реИрдВ:
 template <class R1, class R2> struct minus { typedef rational_t<R1::a * R2::b - R2::a * R1::b, R1::b * R2::b> type1; typedef typename reduce<type1>::type type; }; template <class R1, class R2> struct mult { typedef rational_t<R1::a * R2::a, R1::b * R2::b> type1; typedef typename reduce<type1>::type type; }; template <class R1, class R2> struct divide { typedef rational_t<R1::a * R2::b, R1::b * R2::a> type1; typedef typename reduce<type1>::type type; }; 

рддреБрд▓рдирд╛ рдСрдкрд░реЗрд╢рди:
 template <class R1, class R2> struct less { static const bool value = (R1::a * R2::b - R2::a * R1::b) < 0; }; 

рдХрдореА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдореЗрдЯрд╛рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВред 64-рдмрд┐рдЯ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рднрдВрдбрд╛рд░рдг рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХрддрдо рдЕрдиреБрдореЗрдп рд╕рдВрдЦреНрдпрд╛ (2 ^ 64) ^ 0.5 / 2 = 1ll << 31 рд╣реЛрдЧреА, рдЗрд╕рд▓рд┐рдП:
 template <class R> struct require_reduce { const static int64_t max = (1ll<<31); const static bool value = (R::a >= max) || (R::b >= max); }; 

рдореВрд▓реНрдп рдХрд╛ рдорддрд▓рдм рдЕрдВрд╢ рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЕрдиреНрдпрдерд╛ рдСрдкрд░реЗрд╢рди рдХреЗ рджреМрд░рд╛рди рдЕрддрд┐рдкреНрд░рд╡рд╛рд╣ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
рдЕрдВрд╢ рдХреЛ рдкрд╣рд▓реЗ рдареАрдХ рд╕реЗ рдШрдЯрд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП - рдЬреАрд╕реАрдбреА рджреНрд╡рд╛рд░рд╛ рд╡рд┐рднрд╛рдЬрди рдХреЗ рдЖрдзрд╛рд░ рдкрд░ (рдХрдо рдХрд░реЗрдВ)
рдпрджрд┐ рдХрдореА рд╡рд┐рдлрд▓ рд░рд╣реА, рддреЛ рдЕрдВрд╢ рдХреЛ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдХреЗ рдЧрд▓рдд рддрд░реАрдХреЗ рд╕реЗ рдШрдЯрд╛рдПрдВ рдФрд░
рд╣рд░ 2 рдкрд░ рд╣реИ (рдХрдо рдХрд░реЗрдВ)
рд╕рд╛рдл-рд╕реБрдерд░реА рдХрдЯреМрддреА рдХреЗ рдореЗрдЯрд╛-рдлрдВрдХреНрд╢рди рдХреА рдШреЛрд╖рдгрд╛ рдХрд░реЗрдВ:
 template <bool, class R> struct reduce_accurate; 

рдЧрд▓рдд рдХрдЯреМрддреА, рдЬрд┐рд╕рдХреЗ рдмрд╛рдж рдлрд┐рд░ рд╕реЗ рдХрдо рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ
рдзреНрдпрд╛рди рд╕реЗ, рдЬрдм рддрдХ, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ:
 template <bool, class R> struct reduce_inaccurate { typedef rational_t<(R::a >> 1), (R::b >> 1)> type_; typedef typename reduce_accurate<require_reduce<type_>::value, type_>::type type; }; 

рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИ, рддреЛ рдПрдХ рдореИрд▓рд╛ рдХрдореА рдПрдХ рд╣реА рдореВрд▓реНрдп рд▓реМрдЯрд╛рддреА рд╣реИ:
 template <class R> struct reduce_inaccurate<false, R> { typedef R type; }; 

рдПрдХ рд╕рд╛рдл рдХрдореА рдХреЗ рд▓рд┐рдП, рдЙрдиреНрд╣реЛрдВрдиреЗ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рдЬреАрд╕реАрдбреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджрд┐рдпрд╛, рдпрд╣ рдЗрд╕рдХреЗ рд╕рд╛рде рддреЗрдЬ рд╣реЛ рдЧрдпрд╛, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдЙрдореНрдореАрдж рдереА рдХрд┐ рдирд╣реАрдВред
рдЬреАрд╕реАрдбреА рдХреА рдЧрдгрдирд╛ (рдзрдиреНрдпрд╡рд╛рдж рдЧреНрд░рд┐рдЬрд╝реЛрдмреНрд░ ):
 template <int64_t m, int64_t n> struct gcd; template <int64_t a> struct gcd<a, 0> { static const int64_t value = a; }; template <int64_t a, int64_t b> struct gcd { static const int64_t value = gcd<b, a % b>::value; }; 


рдХрдЯреМрддреА рдлрд╝рдВрдХреНрд╢рди рдЬреАрд╕реАрдбреА рдореЗрдВ рдЕрдВрд╢ рдФрд░ рднрд╛рдЬрдХ рдХреЛ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ, рддреЛ рдЧрд▓рдд рдХрдЯреМрддреА рдХрд░рддрд╛ рд╣реИред
 template <bool, class R> struct reduce_accurate { template <bool, class R> struct reduce_accurate { const static int64_t new_a = R::a / gcd<R::a, R::b>::value; const static int64_t new_b = R::b / gcd<R::a, R::b>::value; typedef rational_t<new_a, new_b> new_type; typedef typename reduce_inaccurate<require_reduce<new_type>::value, new_type>::type type; }; }; 

рдпрджрд┐ рд╕рдЯреАрдХ рдХрдореА рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИ, рддреЛ рдПрдХ рдЧрд▓рдд рдкреНрд░рджрд░реНрд╢рди рдХрд░реЗрдВ:
 template <class R> struct reduce_accurate<false, R> { typedef typename reduce_inaccurate<require_reduce<R>::value, R>::type type; }; 


рдЪрд▓реЛ рд╕рдмрд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рднрд╛рдЧ рдкрд░ рдЪрд▓рддреЗ рд╣реИрдВ, рд╣рдо рдиреНрдпреВрдЯрди рдХреА рд╡рд┐рдзрд┐ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд░реВрдЯ рдХреА рдЧрдгрдирд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд▓рд┐рдЦреЗрдВрдЧреЗред
рдпрд╣ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╕рдЯреАрдХ рд╣реЛрдиреЗ рдХрд╛ рджрд╛рд╡рд╛ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
  : sqrt_eval(p, res, x) { t1 = x/res t2 = res+t1 tmp = t2/2 if (p-1 == 0) return tmp; return sqrt_eval(p-1, tmp, x) } 

Rational_t тАЛтАЛрдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛:
 template <int64_t p, class res, class x> struct sqrt_eval { typedef typename divide<x, res>::type t1; typedef typename plus<res, t1>::type t2; typedef typename divide<t2, rational_t<2,1> >::type tmp; typedef typename sqrt_eval<p-1, tmp, x>::type type; }; template <class res, class x> struct sqrt_eval<0, res, x> { typedef res type; }; 


 sqrt(x) { res = (x + 1)/2 return sqrt_eval(15, res, x) } 

15 - рдиреНрдпреВрдЯрди рдХреЗ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдореЗрдВ рдЪрд░рдгреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ред
 template <class x> struct sqrt { typedef typename divide< typename plus<x, rational_t<1,1> >::type, rational_t<2,1> >::type res; typedef typename sqrt_eval<15, res, x>::type type; }; template <int64_t a> struct sqrt< rational_t<0, a> > { static const int64_t value = 0; }; 

рдПрдХ рдЙрджрд╛рд╣рд░рдг:
 #include <iostream> #include "rational_algo.hpp" int main() { std::cout.precision(15); const double s = rational::sqrt<RATIONAL(2,0)>::type::get(); std::cout << s << std::endl; std::cout << 2-s*s << std::endl; return 0; } 


рдЙрджрд╛рд╣рд░рдг рдкреВрд░реА рдлрд╝рд╛рдЗрд▓: pastebin.com/ea7S2KTd
рдкреНрд░реЛрдЬреЗрдХреНрдЯ: github.com/korkov/rational

UPD: рдпрд╣ рдПрдХ рдЕрдкрдбреЗрдЯреЗрдб рд╡рд░реНрдЬрди рд╣реИ, рдЯрд┐рдкреНрд╕ рдФрд░ рдХрд░реЗрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рд╕рднреА рдХрд╛ рдзрдиреНрдпрд╡рд╛рджред

Source: https://habr.com/ru/post/In124963/


All Articles