Overview
In software Engineering and Computer Science or Mathematics, someone often wants to know how many digits there are in an arbitrary or given number. The equation for this is simple.
Wrong Solution
numdigits=round(logbn)=round(log n/log b)
or
numdigits=int(logbn)+1=int(log n/log b)+1
rendered in mathml (so far only firefox supports it and firefox is buggy with msub):
b or base is the number base (2=binary, 8=octal, 10=decimal, 16=hexadecimal). most people's numbering system is base 10, the arabic numbering system, since we have 10 fingers.
n is the arbitrary given number you want to find a result for.
round is a function that rounds up or down depending on whether or not the real part trips past 0.5, leaving only an integer. round is defined as this: if the number modulus 1 is ≥ 0.5, it returns floor(number+1) else it returns floor(number). floor is a function that strips away the real part of a number and returns only the integer part.
You can use ln (natural logarithm which is
both of these wrong results yeild horrible results upon proper results testing.
Examples
binary (base 2) 10101000 (converts to decimal 168). on a calculator, log 168/log 2=7.392317423. round(7.392317423)=7. indeed, there are 7 digits.
octal (base 8) 76543210 (converts to decimal 16434824). on a calculator, log 16434824/log 8=7.990084224. round(7.990084224)=8. indeed, there are 8 digits.
decimal (base 10) 400 (converts to decimal 400). on a calculator, log 400/log 10=2.602059991. round(2.602059991)=3. indeed, there are 3 digits.
hexadecimal (base 16) FEED (converts to decimal 65261). on a calculator, log 65261/log 16=3.998483368. round(3.998483368)=4. indeed, there are 4 digits.
Solution
the above functions are incorrect. it gives incorrect results. I got better results, (but not perfect) with numdigits=ceil(log number/log base)+1-((log number/log base)-floor(log number/log base)). my instructor was wrong. I am experimenting to find out what is the correct function for this. the closest I have gotten was
#include <tr1/stdint.h>
using namespace std;
int64_t numdigits(int64_t number, int64_t base) {
if (0==number) {
return 1;
}
double lb=log(number)/log(base);
return ceil(lb)+1-(lb-floor(lb));
/*
lb-floor(lb) represents the fractional
part (everything after the decimal point).
1-the above is basically a reverse of
the range of the fractional part.
the above is added to ceil(lb), which has
proved to be closer to the actual
result in most cases.
the whole result is converted to an
integer (equivalent of floor().
*/
}
but like all of the equations I have seen and tested, it fails. this one fails the least. it fails every sequence of 000, for example, 1000, 1000000, 1000000000. I am not sure why. it may have something to do with floating point error. With floating point you have no guarantees of good results. If you want accurate results, use integers instead.
a sure-fire method is:
#include <tr1/stdint.h>
using namespace std;
//this should work for negative numbers.
int64_t numdigits(int64_t number, int64_t base) {
int64_t divided, numdigits=0;
if (0 == number) {return 1;}
while (0 != number) {
number /= base;
numdigits++
}
return numdigits;
}
//this should work with negative numbers.
int64_t numdigits(int64_t number) {
char numstr[100];
#if defined(__MINGW32__)||defined(__BORLANDC__)||defined(_MSC_VER)
int64_t n=sprintf(numstr, "%I64d", number);
#if defined(__DJGPP__)
int64_t n=sprintf(numstr, "%lld", number);
#endif
if (n < 0) {
return n-1; //account for sign and don't include it
} else {
return n;
}
}
while n>0, while n!=0, , , , , , , , , , , , , ,