Mathematically determine the precision and scale of a decimal value

This is how you get the scale using the GetBits() function:

decimal x = 12345.67890M;
int[] bits = decimal.GetBits(x);
byte scale = (byte) ((bits[3] >> 16) & 0x7F); 

And the best way I can think of to get the precision is by removing the fraction point (i.e. use the Decimal Constructor to reconstruct the decimal number without the scale mentioned above) and then use the logarithm:

decimal x = 12345.67890M;
int[] bits = decimal.GetBits(x);
//We will use false for the sign (false =  positive), because we don't care about it.
//We will use 0 for the last argument instead of bits[3] to eliminate the fraction point.
decimal xx = new Decimal(bits[0], bits[1], bits[2], false, 0);
int precision = (int)Math.Floor(Math.Log10((double)xx)) + 1;

Now we can put them into extensions:

public static class Extensions{
    public static int GetScale(this decimal value){
    if(value == 0)
            return 0;
    int[] bits = decimal.GetBits(value);
    return (int) ((bits[3] >> 16) & 0x7F); 
    }

    public static int GetPrecision(this decimal value){
    if(value == 0)
        return 0;
    int[] bits = decimal.GetBits(value);
    //We will use false for the sign (false =  positive), because we don't care about it.
    //We will use 0 for the last argument instead of bits[3] to eliminate the fraction point.
    decimal d = new Decimal(bits[0], bits[1], bits[2], false, 0);
    return (int)Math.Floor(Math.Log10((double)d)) + 1;
    }
}

And here is a fiddle.