How to get the size of a number in .net?

Nir picture Nir · Jul 28, 2011 · Viewed 6.9k times · Source

I want with a given double number to return its "size" (known as |number|, or number of digit without the numbers after the dot), for example:

12.324654 -> 2
12 -> 2
0.99 -> 0
1.01 -> 1
901 -> 3
-0.99 -> 0
-9.999 -> 1

There must be a function is .net that I dont familiar with that does it..

Thanks.

Answer

Ilmari Karonen picture Ilmari Karonen · Jul 28, 2011

Try log10(max(abs(number), 0.5)) + 1 rounded down.

Or, in actual C# syntax:

(int)(Math.Log10(Math.Max(Math.Abs(number), 0.5)) + 1)

OK, how does that work?

At first of all, p = log10(x) is the base-10 logarithm of x; that is to say, the value such that 10 raised to the p-th power (or 1 followed by p zeros) equals x. The logarithm essentially measures the length of the number, except that it's a smooth function of x:

Graph of the base-10 logarithm of x

(Note that, in languages that don't provide a base-10 logarithm function, we can always calculate it as log10(x) = log(x) / log(10), where log() is the logarithm function in any base.)

For example, we have

log10(1) = 0.0
log10(10) = 1.0
log10(100) = 2.0
log10(1000) = 3.0

but also e.g.:

log10(5) = 0.69897
log10(50) = 1.69897
log10(500) = 2.69897
log10(5000) = 3.69897

In general, n ≤ log10(x) < n+1 whenever 10nx < 10n+1.

Looking at the values above, it should be easy enough to see that, to get the number of base-10 digits in a whole number, we should round its base-10 logarithm down to the nearest whole number and add 1 (because we want the length of 10 to be 2, not 1).

However, there are a few more edge cases to consider:

First, the original questioner wanted the length of −x to equal the length of x. The logarithm is only defined for positive numbers, so we replace x by its absolute value to make it always positive.

Second, the original questioner also wanted the length of numbers between 0 and 1 to be zero. The logarithm, however, can take arbitrarily large negative values:

log10(0.1) = −1.0
log10(0.01) = −2.0
log10(0.001) = −3.0
log10(0.0001) = −4.0

and indeed, log10(0) = −∞. To satisfy this requirement, we simply make sure that the number whose length we calculate can never go below 0.5 by using the maximum of it and 0.5 as the input to log10(). (We could use any number between 0.1 and 1 as the cutoff, but 0.5 happens to be a nice round binary fraction.)

Also, we have to make sure to add +1 to the logarithm before rounding it, so that the number that we round is always non-negative. That's because (int) in C# actually rounds negative numbers up towards zero. For example, since log10(0.5) &approx −0.3, the expression (int)Math.Log10(0.5) + 1 (rounding before addition) would evaluate to 0+1 = 1  rather than the expected 0.