0

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)
}
Joe
  • 59
  • 6

2 Answers2

3

You can split your input real into the integer and fractional parts without looking for dot point.

real_to_int(n) = {
    my(intpart=digits(floor(n)));
    my(fracpartrev=fromdigits(eval(Vecrev(Str(n))[1..-(2+#intpart)])));
    fromdigits(concat(intpart, Vecrev(digits(fracpartrev))))
};

real_to_int(123456789.123456789009876543210000)
> 12345678912345678900987654321

Note, the composition of digits and fromdigits eliminates all the leading zeros from the list of digits for you.

Piotr Semenov
  • 1,761
  • 16
  • 24
  • To use `real_to_int` your code is assumed to set up the proper `realprecision` in order to have exactly all the fractional digits of your real literals. E.g., `default(realprecision, 100)` will allow you to have `99` exact fractional digits for your real literals. So `real_to_int` will have no rounding effects if `realprecision` is adjusted properly. – Piotr Semenov Nov 06 '21 at 20:18
2

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.

K.B.
  • 861
  • 5
  • 14