C function for returning number of digits?

L

Luke Wu

Is there a C function that returns the number of digits in an input
int/long?

example:

numdigits(123) returns 3
numdigits(1232132) returns 7
 
C

Chris McDonald

Luke Wu said:
Is there a C function that returns the number of digits in an input
int/long?

numdigits(123) returns 3
numdigits(1232132) returns 7


Learn about lagarithms, then apply that knowledge to standard C.
 
L

Luke Wu

Chris said:
Learn about lagarithms, then apply that knowledge to standard C.

Ohh my.... didn't think it would be a two liner.......thank you
#include<math.h>

int numdigits(int n)
return log10(n) + 1;
 
W

Walter Roberson

Is there a C function that returns the number of digits in an input
int/long?

numdigits(123) returns 3
numdigits(1232132) returns 7

There is no standard one, no, but you can write your own.

But first you will have to define:
- whether the negative sign counts as a digit or not
- whether +0 and 0 and -0 have different number of digits

Be sure to test your routine against LONG_MIN and LONG_MAX
(which will not necessarily have the same number of digits.)
And don't just take absolute values: it is common for
(-LONG_MIN) to exceed LONG_MAX.
 
R

Richard Heathfield

Luke Wu said:
Is there a C function that returns the number of digits in an input
int/long?

example:

numdigits(123) returns 3
numdigits(1232132) returns 7

int numdigits(int n)
{
int count = 1; /* bound to be at least one digit! */
while(n != 0)
{
n /= 10;
++count;
}
return count;
}

This function ignores signs.

Note that the logarithm method is a little tighter in source terms, but
involves a call to log(), which can be expensive, computationally speaking.
 
R

Richard Heathfield

[attempting to supersede previous (broken) code]

Luke Wu said:
Is there a C function that returns the number of digits in an input
int/long?

example:

numdigits(123) returns 3
numdigits(1232132) returns 7

int numdigits(int n)
{
int count = 0;
do
{
++count;
n /= 10;
}
while(n != 0);
return count;
}

This function ignores signs.

Note that the logarithm method is a little tighter in source terms, but
involves a call to log(), which can be expensive, computationally speaking.
 
R

Richard Bos

Chris McDonald said:
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. Since double is required to
support at least 10 digits, integers of the size the OP used will be
converted correctly, without any floating point error. There may still
be a rounding error _within_ log10(), but that can't be helped, only
worked around.

Richard
 
C

Chris McDonald

Yes. And with #include <math.h>, the ints and doubles will be
automatically converted back and forth. Since double is required to
support at least 10 digits, integers of the size the OP used will be
converted correctly, without any floating point error. There may still
be a rounding error _within_ log10(), but that can't be helped, only
worked around.

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

Keith Thompson

Luke Wu said:
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.
 
R

Richard Bos

Keith Thompson said:
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
 
I

Ingo Menger

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

How about:
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.
 
J

Jirka Klaue

Ingo Menger:
How about:
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
 
N

Niklas Norrthon

Ingo Menger said:
Richard said:
*g* Never knock the simple solution. You're quite right, of course

How about:
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
 
M

Mark McIntyre

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

Walter Roberson

Niklas Norrthon said:
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.
 
I

Ingo Menger

Niklas said:
Ingo Menger said:
Richard said:
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

How about:
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.
 
K

Kevin Handy

Ingo said:
Richard Bos schrieb:

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


How about:
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;
}

but it still might be slower depending on the availability
of a hardware log instruction vs. integer division speed.
 
J

Jordan Abel

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

How about:
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;
 
J

Jordan Abel

Ingo said:
Richard Bos schrieb:

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


How about:
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]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,810
Latest member
Kassie0918

Latest Threads

Top