How to find the $n^{th}$ digit (in Maple)

2.2k Views Asked by At

Given a number, such as $5^{9^6}$, how would I find the $n^{th}$ digit? (say the $87^{th}$ digit)

I considered the "Digits" command, but that only controls the amount of digits after the decimal, so I can't find any use for it for integer values. Any hints or useful commands would be appreciated. Thanks.

3

There are 3 best solutions below

1
On BEST ANSWER

This procedure:

nthdigit := proc (n, k)
local d, m;
d := convert(n, base, 10);
m := nops(d);
return d[m+1-k];
end proc;

takes as input natural numbers $n$ and $k$ and returns the $k^{th}$ digit of $n$.

For example
nthdigit(5^(9^5), 87);
returns 8.

0
On

Start by finding how many digits your number has (take $\log_{10}$ of your number and round it up). In this case I think you get $371462$ digits.

Now, your $87^{th}$ digit is the $371462-87$th digit from the end, thus is the last digit of the integral part of $$\frac{5^{9^6}}{10^{371462-87}} \,.$$

In general, and this is probably an ugly way to do this, to find the $k$th digit of some number $n$, you calculate

$$\lfloor \frac{n}{10^{ \lceil \log_{10}n\rceil -k \rfloor}} \rfloor \pmod{10} $$

0
On

Some timings may be of interest.

Note that procedure f below can go awry for obtaining the 1st digit of n=10^N where N is of type nonnegint. That is easily done without Maple, of course, but it's undesirable to have unnecessary corner cases in one's code.

Also, as given procedure nthdigit doesn't allow a float as the first argument. The others do, ignoring the decimal point (but that could be accommodated differently).

None of these check whether n has few than k digits.

The first approach g below computes a float approximation and then picks off the mantissa. The command SFloatMantissa could be used instead of op(1,...), if that make it clearer.

There is some savings to be had by using kernel builtin trunc instead of floor, but even with that g will outpace h below to handle 5^(9^6) in the stated example.

These timings were done in 64bit Maple 17.01 on Windows 7. There may be differences if using 32bit Maple, for some examples, since the cutoff for immediate integers is smaller.

restart:

g:=proc(x, d)
    Rounding:=-infinity;
    op(1,evalf[d](x)) mod 10;
end proc:

CodeTools:-Usage( g(5^(9^5), 87) );
memory used=217.98KiB, alloc change=0 bytes, cpu time=0ns, real time=2.00ms
                               8

CodeTools:-Usage( g(5^(9^6), 87) );
memory used=1.97MiB, alloc change=0 bytes, cpu time=16.00ms, real time=19.00ms
                               6

restart:
h:=proc(x, d)
    floor(x/10^((ilog[10](x)+1)-d)) mod 10;
end proc:

CodeTools:-Usage( h(5^(9^5), 87) );
memory used=0.77MiB, alloc change=0 bytes, cpu time=0ns, real time=5.00ms
                               8
CodeTools:-Usage( h(5^(9^6), 87) );
memory used=6.29MiB, alloc change=0 bytes, cpu time=62.00ms, real time=61.00ms
                               6

restart:
f:=proc(x, d)
    floor(x/10^(ceil(log[10](x))-d)) mod 10;
end proc:

CodeTools:-Usage( f(5^(9^5), 87) );
memory used=18.21MiB, alloc change=24.00MiB, cpu time=109.00ms, real time=113.00ms
                               8

CodeTools:-Usage( f(5^(9^6), 87) );
memory used=179.28MiB, alloc change=17.53MiB, cpu time=1.62s, real time=1.62s
                               6

restart:
nthdigit := proc (n, k)
    local d, m; 
    d := convert(n, base, 10); 
    m := nops(d); 
    return d[m+1-k]; 
end proc:

CodeTools:-Usage( nthdigit(5^(9^5), 87) );
memory used=344.99MiB, alloc change=51.50MiB, cpu time=843.00ms, real time=851.00ms
                               8

CodeTools:-Usage( nthdigit(5^(9^6), 87) );
memory used=26.74GiB, alloc change=26.84MiB, cpu time=55.21s, real time=54.76s
                               6

Also, somewhat fast (but not faster than g or h above) is,

restart:
s:=proc(x, d)
   parse(StringTools:-Substitute(sprintf("%a",x),".","")[d]);
end proc:

CodeTools:-Usage( s(5^(9^5), 87) );
memory used=1.26MiB, alloc change=0 bytes, cpu time=0ns, real time=12.00ms
                               8

CodeTools:-Usage( s(5^(9^6), 87) );
memory used=16.15MiB, alloc change=0 bytes, cpu time=124.00ms, real time=115.00ms
                               6

By the way, is there supposed to be some super fast way? Ie, was is a challenge or competition question of some sort?