Velocity Reviews > C function for returning number of digits?

# C function for returning number of digits?

Richard Bos
Guest
Posts: n/a

 11-29-2005
Keith Thompson <(E-Mail Removed)> wrote:

> "Luke Wu" <(E-Mail Removed)> writes:
> > Ohh my.... didn't think it would be a two liner.......thank you
> > #include<math.h>
> >
> > int numdigits(int n)
> > return log10(n) + 1;

>
> I don't think a floating-point solution is best here. A loop using
> integer arithmetic is likely to be faster and more accurate. For that
> matter, a binary search on a lookup table holding powers of 10 is
> likely to be even quicker.

*g* Never knock the simple solution. You're quite right, of course.

Richard

Ingo Menger
Guest
Posts: n/a

 11-29-2005

Richard Bos schrieb:

> Keith Thompson <(E-Mail Removed)> wrote:
>
> > "Luke Wu" <(E-Mail Removed)> writes:
> > > Ohh my.... didn't think it would be a two liner.......thank you
> > > #include<math.h>
> > >
> > > int numdigits(int n)
> > > return log10(n) + 1;

> >
> > I don't think a floating-point solution is best here. A loop using
> > integer arithmetic is likely to be faster and more accurate. For that
> > matter, a binary search on a lookup table holding powers of 10 is
> > likely to be even quicker.

>
> *g* Never knock the simple solution. You're quite right, of course

int length;
char digits[100]; /* should be big enough even for 128 bit longs */
sprintf(digits, "%d", n);
length = strlen(digits) - (n<0 ? 1 : 0);

Boxing this code in a function and/or handling special cases (has 0 1
digit or none?) is left as exercise for the OP.

Jirka Klaue
Guest
Posts: n/a

 11-29-2005
Ingo Menger:
>>> Luke Wu:

>>>> #include<math.h>
>>>>
>>>> int numdigits(int n)
>>>> return log10(n) + 1;

> int length;
> char digits[100]; /* should be big enough even for 128 bit longs */
> sprintf(digits, "%d", n);
> length = strlen(digits) - (n<0 ? 1 : 0);

length = snprintf(0, 0, "%d", n); /* C99 */

Jirka

Niklas Norrthon
Guest
Posts: n/a

 11-29-2005
"Ingo Menger" <(E-Mail Removed)> writes:

> Richard Bos schrieb:
>
> > Keith Thompson <(E-Mail Removed)> wrote:
> >
> > > "Luke Wu" <(E-Mail Removed)> writes:
> > > > Ohh my.... didn't think it would be a two liner.......thank you
> > > > #include<math.h>
> > > >
> > > > int numdigits(int n)
> > > > return log10(n) + 1;
> > >
> > > I don't think a floating-point solution is best here. A loop using
> > > integer arithmetic is likely to be faster and more accurate. For that
> > > matter, a binary search on a lookup table holding powers of 10 is
> > > likely to be even quicker.

> >
> > *g* Never knock the simple solution. You're quite right, of course

>
> int length;
> char digits[100]; /* should be big enough even for 128 bit longs */
> sprintf(digits, "%d", n);
> length = strlen(digits) - (n<0 ? 1 : 0);

And how do you fix this when the next version of your compiler ships
(which use 333 bit longs)?

A solution using snprintf could work, but io functions are quite complex
so I'd not be surprised if the log10 was faster. Personally I'd go for
either a counting loop, or a binary lookup table, depending on how
critical speed, and time for implementation are.

/Niklas Norrthon

Mark McIntyre
Guest
Posts: n/a

 11-29-2005
On Tue, 29 Nov 2005 08:07:37 +0000 (UTC), in comp.lang.c , Chris
McDonald <(E-Mail Removed)> wrote:

>(E-Mail Removed) (Richard Bos) writes:
>
>>Chris McDonald <(E-Mail Removed)> wrote:

>
>>> "Luke Wu" <(E-Mail Removed)> writes:
>>>
>>> >int numdigits(int n)
>>> > return log10(n) + 1;
>>>
>>> Check its prototype - it's double log10(double x);

>>Yes. And with #include <math.h>, the ints and doubles will be
>>automatically converted back and forth.

>
>Thanks; my mistake.
>Perhaps my coding style tends to be too pedantic, as I would have employed
>casts in both places.

As a general rule, you shold only use casts when
a) you actually need one; or
b) it makes the code less ambiguous

This could be argued as a (b) since it would show that you really did
intend to return an int, and would prevent maintenance droids from
changing it in a tidy-up frenzy. Personally I don't think it does,
since the function name/purpose is self-documenting. YMMV.
--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----

Walter Roberson
Guest
Posts: n/a

 11-29-2005
In article <(E-Mail Removed)>,
Niklas Norrthon <(E-Mail Removed)> wrote:

>And how do you fix this when the next version of your compiler ships
>(which use 333 bit longs)?

>A solution using snprintf could work, but io functions are quite complex
>so I'd not be surprised if the log10 was faster. Personally I'd go for
>either a counting loop, or a binary lookup table, depending on how
>critical speed, and time for implementation are.

If one is assuming that the next generation compiler might have 333 bit
longs (and of course the DS9000 has 666 bit longs whenever it feels like
it ), then one would need to initialize the binary lookup table
at runtime. The code to do that without risking overflow (UB) is
probably not so long, but is likely a bit interesting.
--
Okay, buzzwords only. Two syllables, tops. -- Laurie Anderson

Ingo Menger
Guest
Posts: n/a

 11-29-2005

Niklas Norrthon schrieb:

> "Ingo Menger" <(E-Mail Removed)> writes:
>
> > Richard Bos schrieb:
> >
> > > Keith Thompson <(E-Mail Removed)> wrote:
> > >
> > > > "Luke Wu" <(E-Mail Removed)> writes:
> > > > > Ohh my.... didn't think it would be a two liner.......thank you
> > > > > #include<math.h>
> > > > >
> > > > > int numdigits(int n)
> > > > > return log10(n) + 1;
> > > >
> > > > I don't think a floating-point solution is best here. A loop using
> > > > integer arithmetic is likely to be faster and more accurate. For that
> > > > matter, a binary search on a lookup table holding powers of 10 is
> > > > likely to be even quicker.
> > >
> > > *g* Never knock the simple solution. You're quite right, of course

> >
> > int length;
> > char digits[100]; /* should be big enough even for 128 bit longs */
> > sprintf(digits, "%d", n);
> > length = strlen(digits) - (n<0 ? 1 : 0);

>
> And how do you fix this when the next version of your compiler ships
> (which use 333 bit longs)?

I don't. I write the length of the char array as constant expression
involving sizeof (long) in the first place. For example
char digits[32 + 4 * sizeof (long)]
That should do it.

Kevin Handy
Guest
Posts: n/a

 11-29-2005
Ingo Menger wrote:
> Richard Bos schrieb:
>
>
>>Keith Thompson <(E-Mail Removed)> wrote:
>>
>>
>>>"Luke Wu" <(E-Mail Removed)> writes:
>>>
>>>>Ohh my.... didn't think it would be a two liner.......thank you
>>>>#include<math.h>
>>>>
>>>>int numdigits(int n)
>>>> return log10(n) + 1;
>>>
>>>I don't think a floating-point solution is best here. A loop using
>>>integer arithmetic is likely to be faster and more accurate. For that
>>>matter, a binary search on a lookup table holding powers of 10 is
>>>likely to be even quicker.

>>
>>*g* Never knock the simple solution. You're quite right, of course

>
>
> int length;
> char digits[100]; /* should be big enough even for 128 bit longs */
> sprintf(digits, "%d", n);
> length = strlen(digits) - (n<0 ? 1 : 0);
>
> Boxing this code in a function and/or handling special cases (has 0 1
> digit or none?) is left as exercise for the OP.
>

Is sprintf followed by a strlen actually any faster than log10?
for sign.

How about a simple integer loop (destroys n, so make a copy
if you need to keep it)

int length;
while(n)
{
length++;
n /= 10;
}

but it still might be slower depending on the availability

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----

Jordan Abel
Guest
Posts: n/a

 11-29-2005
On 2005-11-29, Ingo Menger <(E-Mail Removed)> wrote:
>
> Richard Bos schrieb:
>
>> Keith Thompson <(E-Mail Removed)> wrote:
>>
>> > "Luke Wu" <(E-Mail Removed)> writes:
>> > > Ohh my.... didn't think it would be a two liner.......thank you
>> > > #include<math.h>
>> > >
>> > > int numdigits(int n)
>> > > return log10(n) + 1;
>> >
>> > I don't think a floating-point solution is best here. A loop using
>> > integer arithmetic is likely to be faster and more accurate. For that
>> > matter, a binary search on a lookup table holding powers of 10 is
>> > likely to be even quicker.

>>
>> *g* Never knock the simple solution. You're quite right, of course

>
> int length;
> char digits[100]; /* should be big enough even for 128 bit longs */
> sprintf(digits, "%d", n);
> length = strlen(digits) - (n<0 ? 1 : 0);

For c99:

length = snprintf(0,0,"%d",n)-1;

> Boxing this code in a function and/or handling special cases (has 0 1
> digit or none?) is left as exercise for the OP.

Jordan Abel
Guest
Posts: n/a

 11-29-2005
On 2005-11-29, Kevin Handy <(E-Mail Removed)> wrote:
> Ingo Menger wrote:
>> Richard Bos schrieb:
>>
>>
>>>Keith Thompson <(E-Mail Removed)> wrote:
>>>
>>>
>>>>"Luke Wu" <(E-Mail Removed)> writes:
>>>>
>>>>>Ohh my.... didn't think it would be a two liner.......thank you
>>>>>#include<math.h>
>>>>>
>>>>>int numdigits(int n)
>>>>> return log10(n) + 1;
>>>>
>>>>I don't think a floating-point solution is best here. A loop using
>>>>integer arithmetic is likely to be faster and more accurate. For that
>>>>matter, a binary search on a lookup table holding powers of 10 is
>>>>likely to be even quicker.
>>>
>>>*g* Never knock the simple solution. You're quite right, of course

>>
>>
>> int length;
>> char digits[100]; /* should be big enough even for 128 bit longs */
>> sprintf(digits, "%d", n);
>> length = strlen(digits) - (n<0 ? 1 : 0);
>>
>> Boxing this code in a function and/or handling special cases (has 0 1
>> digit or none?) is left as exercise for the OP.
>>

>
> Is sprintf followed by a strlen actually any faster than log10?
> I'm dubious about it on modern hardware. Plus the additional test
> for sign.
>
> How about a simple integer loop (destroys n, so make a copy
> if you need to keep it)
>
> int length;
> while(n)
> {
> length++;
> n /= 10;
> }

Both log10 and this also fall flat on negative numbers. a negative
number divided by a positive number is permitted to never result in
zero; and of course the log of a negative number is non-real. At least
the sprintf solution returns something that some people _might_ consider
sensible even in the naivest implementation [counting the minus as a
digit]