Hi GiNaC! Is there a way to convert floating point numbers to rational numbers? And, expressions with floating point numbers to expressions with rational numbers? wxmaxima has the function "rationalize"; I did notice there is a rationalize <https://www.ginac.de/CLN/cln.html#Conversion-to-rational-numbers> function in the CLN library; is that what I should work with? Thanks! Charles
On Tue, 18 Jul 2023 18:55:17 -1000, Charles White <whitece6@hawaii.edu> said:
CW> Hi GiNaC! Is there a way to convert floating point numbers to CW> rational numbers? And, expressions with floating point numbers CW> to expressions with rational numbers? wxmaxima has the function CW> "rationalize"; I did notice there is a rationalize CW> <https://www.ginac.de/CLN/cln.html#Conversion-to-rational-numbers> CW> function in the CLN library; is that what I should work with? Yes, see the code below as an example. Probably, we can add something like that to the GiNaC itself if the maintainers see it meaningful. I am also wondering why do we not have a trivial constructor: numeric::numeric(cln::cl_N v) { value = v; } in the GiNaC? Best wishes, Vladimir -- Vladimir V. Kisil http://www1.maths.leeds.ac.uk/~kisilv/ Book: Geometry of Mobius Maps https://doi.org/10.1142/p835 Soft: Geometry of cycles http://moebinv.sourceforge.net/ Jupyter notebooks: https://github.com/vvkisil?tab=repositories ================================================== #include <iostream> #include <ginac/ginac.h> #include <cln/cln.h> using namespace std; using namespace GiNaC; struct map_rationalize_ex : public map_function { ex operator()(const ex &e) { if (is_a<numeric>(e)) { cln::cl_N e_N = ex_to<numeric>(e).to_cl_N(); cln::cl_RA e_R = rationalize(cln::realpart(e_N)); cln::cl_RA e_I = rationalize(cln::imagpart(e_N)); return numeric(cln::cl_I_to_long(numerator(e_R)), cln::cl_I_to_long(denominator(e_R))) + I * numeric(cln::cl_I_to_long(numerator(e_I)), cln::cl_I_to_long(denominator(e_I))); } else if (e.nops() > 0) return e.map(*this); else return e; } }; int main() { symbol x("x"), y("y"); ex e = 0.5*sin((.6+I*.3)*x +exp(.25*y+.3333+I*numeric(1,7)))+pow(.4*x, .6); map_rationalize_ex rationalize_ex; cout << e << endl << "is rationalised to" << endl << rationalize_ex(e) << endl; return 0; }
On Wed, 19 Jul 2023 10:42:35 +0100, "Vladimir V. Kisil" <V.Kisil@leeds.ac.uk> said: VVK> Yes, see the code below as an example.
It is easy to see that rationalize function from CLN produces huge fractions due to floating point errors. I am including a second method based on the continued fraction approximations. Its behaviour can be adjusted through parameters tolerance and cf_size. -- Vladimir V. Kisil http://www1.maths.leeds.ac.uk/~kisilv/ Book: Geometry of Mobius Maps https://doi.org/10.1142/p835 Soft: Geometry of cycles http://moebinv.sourceforge.net/ Jupyter notebooks: https://github.com/vvkisil?tab=repositories #include <iostream> #include <ginac/ginac.h> #include <math.h> using namespace std; using namespace GiNaC; int tolerance = 1E6; int cf_size = 15; numeric rationalize(numeric x) { if (ex_to<numeric>(x).is_rational()) return x; x = ex_to<numeric>(evalf(x)); int sign = (x.is_positive() ? +1 : -1); double xf= abs(x.to_double()); lst coeff = lst{}; for (int i = 0; i < cf_size; ++i ) { if ( xf > tolerance ) break; else { int base = floor(xf); coeff.append(numeric(base)); if (xf - base == 0) break; xf = 1/(xf-base); } } lst::const_reverse_iterator i = coeff.rbegin(); numeric res = ex_to<numeric>(*i); ++i; while ( i != coeff.rend()) { res = ex_to<numeric>(*i) + 1/res; ++i; } return sign*res; } struct map_rationalize_ex : public map_function { ex operator()(const ex &e) { if (is_a<numeric>(e)) return rationalize(ex_to<numeric>(e).real()) + I * rationalize(ex_to<numeric>(e).imag()); else if (e.nops() > 0) return e.map(*this); else return e; } }; int main() { symbol x("x"), y("y"); ex e = 0.5*sin((-.6+I*.3)*x +exp((.25-I*.8)*y+.3333-I*numeric(1,7)))+pow(.4*x, .6); map_rationalize_ex rationalize_ex; cout << e << endl << "is rationalised to" << endl << rationalize_ex(e) << endl; return 0; }
participants (2)
-
Charles White
-
Vladimir V. Kisil