Search code examples
pari-gp

Is there a better way to extract the digits of a real number using Pari/GP?


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)
}

Solution

  • 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.