Here's my current code, but it's ugly and I'm worried about possible edge cases from very large or small numbers. Is there a better way to do this?
real_to_int(n)={
if(n==floor(n),return(floor(n))); \\ If "n" is a whole number we're done
my(v=Vec(strprintf("%g",n))); \\ Convert "n" to a zero-padded character vector
my(d=sum(i=1,#v,i*(v[i]=="."))); \\ Find the decimal point
my(t=eval(concat(v[^d]))); \\ Delete the decimal point and reconvert to a number
my(z=valuation(t,10)); \\ Count trailing zeroes
t/=10^z; \\ Get rid of trailing zeroes
return(t)
}
The problem is not well defined since the conversion from real number (stored internally in binary) to a decimal string may require rounding and how this is done depends on a number of factors such as the format
default, or the current bitprecision
.
What is possible is to obtain the internal binary representation of the t_REAL
as m * 2^e, where m
and e
are both integers.
install(mantissa2nr, GL);
real_to_int(n) =
{
e = exponent(n) + 1 - bitprecision(n);
[mantissa2nr(n, 0), e];
}
? [m, e] = real_to_int(Pi)
%1 = [267257146016241686964920093290467695825, -126]
? m * 1. * 2^e
%2 = 3.1415926535897932384626433832795028842
With [m, e] we obtain the exact (rational) internal representation of the number and both are well defined, i.e., independent of all settings. m
is the binary equivalent of what was requested in decimal.