Question: van Vliet: proc log10 and op EXPLENGTH
chris hermansen
clhermansen@gmail.com
Sat Mar 14 17:24:12 GMT 2026
Thanks for the reply, Jose.
On Sat, Mar 14, 2026 at 4:36 AM Jose E. Marchesi <jemarch@gnu.org> wrote:
>
> Hi Chris.
>
> > Hello again;
> >
> > van Vliet defines the procedure log10 as:
> >
> > proc {ℵ₀} log10 = (Number v) int:
> > int(pseudo46) { A number P such that, given a value V, P = 0 if |V| <
> 1.0,
> > and, if |V| >= 1.0, then P is such that
> >
> > ENTIER(log[10](|V|)) + 1 <= P <= ENTIER(log[10](|V|)) + 2.
> >
> > Thus, P is an estimate of the number of digits in the integral part
> > of V; this estimate may be at most 1 too large. This definition
> > should allow efficient computation of P; e.g., using the normal
> > floating point_representation of V with a mantissa M and base 2
> > exponent E (E = ENTIER(log[2]|V| )), P may be given the value
> > (ENTIER(log[10]2 * (E+1))+1) MAX 0. Obviously also, 'log10' is a
> > typical candidate for inline expansion. };
> >
> > and the operator EXPLENGTH as:
> >
> > prio {ℵ₀} EXPLENGTH = 9;
> > op EXPLENGTH = (bool sign, int exp) int:
> > int(pseudo47) { The smallest E such that 'whole(exp, ABS sign * E)'
> > succeeds.
> > This operator is used to estimate the length needed to convert the
> > exponent in 'float'. This is probably easier and faster than actually
> > converting the exponent and subsequently testing its width, since on
> > most implementations the exponent will be a relatively small integer
> > (<= 322, say). };
> >
> > For the time being, I propose that for these types of calculations - "the
> > number of digits needed by the integral value X" - we simply use a set of
> > if - then - else - fi.
> >
> > So we could proceed along the lines of:
> >
> > proc {ℵ₀} num_digits = (union (
> > {iter L {short short} {short} {} {long} {long long}}
> > {L} int
> > {reti {,}}
> > ) i) int:
> > begin
> > long long int test =
> > case ABS i in
> > {iter L {short short} {short} {} {long} {long long}}
> > {iter K {LENG LENG LENG LENG} {LENG LENG LENG} {LENG LENG} {LENG} {}}
> > ({L} int ii}: {K} ii
> > {reti {,}}
> > esac;
> > if test < long long 10
> > then 1
> > elif test < long long 100
> > then 2
> > elif test < long long 1000
> > ...
> > elif test < long long 1000000000000000000
> > then 18
> > else 19
> > fi
> > end;
> >
> > Clearly this might not be the most efficient. However, given its use is
> > for formatting, it's probably not too bad as a first cut, and it does
> have
> > the advantage of not requiring logarithms nor ENTIER.
> >
> > Any thoughts?
> > ...
>
> Seems sensible to me.
> This approach is fast if you binary search.
>
I thought about a binary search; do you think it worthwhile? Obviously, if
the numbers passed to num_digits() are uniformly distributed throughout
[0,long_long_max_int] then binary search is the way to go; but I wonder if
most numbers sent to it are clumped closer to zero.
Also I have this idea (unsupported by fact) that there are some kinds of
instructions in the x86 instruction set that make this sort of linear table
lookup very fast.
--
Chris Hermansen · clhermansen "at" gmail "dot" com
C'est ma façon de parler.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/algol68/attachments/20260314/0c34f855/attachment-0001.htm>
More information about the Algol68
mailing list