What's the fastest way to implement
template <typename T>
unsigned highest_decimal_digit(T x);
(which returns e.g. 3 for 356431, 7 for 71 and 9 for 9)?
The best I can think of is:
... but maybe there's another approach.
Notes:
There are a total of 10 digits in the decimal number system. Hence, the largest digit in the decimal number system is from one of the above. Clearly, out of the ones given here, 9 is the largest digit. Thus, 9 is the largest digit in the decimal number system.
The range of a decimal variable or the numbers in a decimal column is -n to +n , where n is the largest positive number that can be represented with the applicable precision and scale. The maximum range is 1 - 10³¹ to 10³¹ - 1.
The maximum number of bytes the database server uses to store a decimal value is 17. One byte is used to store the exponent and sign, leaving 16 bytes to store up to 32 digits of precision.
The best option seems to be to combine CLZ approach and divide by precalculated power of 10. So, in pseudocode:
powers10=[1,1,1,1,10,10,10,10,100,100...]; // contains powers of 10 map to CLZ values
int firstDigit(unsigned INT_TYPE a) {
if (a<10) return a; // one digit, screw it
int j=typesize(a)-clz(a);
if (j==3) return 1; // 10-16 hit this, return 1
int k=a/powers10[j];
if (k>9) return 1; else return k;
}
typesize()
returns 64 for long long
, 32 for int
and 16 for short int
.
Newer x86 chips support an lzcnt instruction that tells you the number of clear bits at the start of an integer. You can access it using built-in compiler functions such as the following (from GCC):
unsigned short __builtin_ia32_lzcnt_16(unsigned short);
unsigned int __builtin_ia32_lzcnt_u32(unsigned int);
unsigned long long __builtin_ia32_lzcnt_u64 (unsigned long long);
You could combine this with a lookup table of 640 values indicating the lower and upper bounds of integers starting with each digit from 0-9 that start with the corresponding number of clear bits. In fact, you could save space by right-shifting the lzcnt
value 3 places; the correspondence with first decimal digits will still be unique.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With