Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

decimal length of +ve integers

16 views
Skip to first unread message

James Cloos

unread,
Nov 3, 2022, 1:43:38 PM11/3/22
to
does cl offer a better way to do? :

(defun decimal-length (+integer)
(length (format nil "~d" +integer)))

-JimC
--
James Cloos <cl...@jhcloos.com> OpenPGP: 0x997A9F17ED7DAEA6

Lieven Marchand

unread,
Nov 3, 2022, 2:42:23 PM11/3/22
to
James Cloos <cl...@jhcloos.com> writes:

> does cl offer a better way to do? :
>
> (defun decimal-length (+integer)
> (length (format nil "~d" +integer)))

One can argue about better but (1+ (floor (log +integer 10))) would also
work.

--
Laat hulle almal sterf. Ek is tevrede om die wêreld te sien brand en die vallende
konings te spot. Ek en my aasdier sal loop op die as van die verwoeste aarde.

Kaz Kylheku

unread,
Nov 3, 2022, 8:55:25 PM11/3/22
to
On 2022-11-03, Lieven Marchand <m...@wyrd.be> wrote:
> James Cloos <cl...@jhcloos.com> writes:
>
>> does cl offer a better way to do? :
>>
>> (defun decimal-length (+integer)
>> (length (format nil "~d" +integer)))
>
> One can argue about better but (1+ (floor (log +integer 10))) would also
> work.

Here is another idea. Let's restrict to nonnegative integers.
Or, well, I see that's already implied by the +integer naming.

Further, let's suppose we just need an lower bound on the number of
digits, but one that is fairly tight: say not excessive by more than 1.

To get that we can avoid taking a logarithm of an integer, which could
be a bignum.

We can use integer-length to get the number of binary digits, and
then estimat the decimal digits required to represent that many
binary digits.

There are (/ (log 10) (log 2)) binary digits in a decimal digit,
so we just have to divide by this value and make a little adjustment.
Or let's reciprocate it:

(defconstant %bit-digits% (/ (log 2) (log 10)))

(defun decimal-length (+integer)
(coerce (ceiling (* (integer-length +integer) %bit-digits%)) 'integer))

(loop for i = 3 then (coerce (truncate (* i (sqrt 2))) 'integer)
while (< i 100000000)
do (format t "~s ~s~%" i (decimal-length i)))
3 1
4 1
5 1
7 1
9 2
12 2
16 2
22 2
31 2
43 2
60 2
84 3
118 3
166 3
234 3
330 3
466 3
659 4
931 4
1316 4
1861 4
2631 4
3720 4
5260 4
7438 4
10518 5
14874 5
21035 5
29747 5
42068 5
59493 5
84135 6
118984 6
168268 6
237966 6
336534 6
475930 6
673066 7
951859 7
1346131 7
1903716 7
2692261 7
3807432 7
5384522 7
7614864 7
10769044 8
15229728 8
21538088 8
30459456 8
43076176 8
60918912 8
86152352 9

Floating-point could be eliminated if we use a rational approximation
for the factor.

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

Paul Rubin

unread,
Nov 3, 2022, 9:15:32 PM11/3/22
to
Kaz Kylheku <864-11...@kylheku.com> writes:
> (loop for i = 3 then (coerce (truncate (* i (sqrt 2))) 'integer)
> while (< i 100000000)
> do (format t "~s ~s~%" i (decimal-length i)))
> 3 1
> 4 1 ...
> 60918912 8
> 86152352 9

Wait, that last one doesn't look right.

This works for me:

(defun decimal-length (n)
(cond
((< n 0) (1+ (ilen (- n))))
((< n 10) 1)
(t (1+ (ilen (/ n 10))))))

Kaz Kylheku

unread,
Nov 3, 2022, 11:07:48 PM11/3/22
to
On 2022-11-04, Paul Rubin <no.e...@nospam.invalid> wrote:
> Kaz Kylheku <864-11...@kylheku.com> writes:
>> (loop for i = 3 then (coerce (truncate (* i (sqrt 2))) 'integer)
>> while (< i 100000000)
>> do (format t "~s ~s~%" i (decimal-length i)))
>> 3 1
>> 4 1 ...
>> 60918912 8
>> 86152352 9
>
> Wait, that last one doesn't look right.

I explained, in not many words, that I bent the requirements: if it
is acceptable to get an upper bound on the numbrer of digits that is not
too excessive (say not by more than one), then this approximate solution
can work.

Like say we wanted to allocate a buffer for the digit string, and didn't
care about an extra byte sometimes.

Nicolas Neuss

unread,
Nov 4, 2022, 7:24:52 AM11/4/22
to
James Cloos <cl...@jhcloos.com> writes:

> does cl offer a better way to do? :
>
> (defun decimal-length (+integer)
> (length (format nil "~d" +integer)))
>
> -JimC

(defun decimal-length (n)
(loop while (plusp n) do
(setf n (floor n 10))
count 1))
0 new messages