Buu
Buu

Reputation: 50345

Convert a decimal to the smallest possible numeric type without any data loss

I want to write a method which converts a decimal to the smallest possible numeric type without any data loss. For examples:

The input of the method is always a decimal and the output is any of the following .NET numeric types: sbyte, byte, short, ushort, int, uint, long, ulong, float, double, and decimal.

I have tried using checked() to catch the OverflowException, however that approach doesn't prevent loss. For example, checked((int)1.1) won't throw any exception and return 1! Therefore, it's not what I want.

Any recommendation?

Update: expected method signature

public object Convert(decimal d)
{
   // return ...
}

Upvotes: 2

Views: 978

Answers (2)

Buu
Buu

Reputation: 50345

This is what I end up doing. Some reflection could be used to reduce the amount of code -- but since this method is called so many times in my app that I feel better this way.

private static object NarrowNumber(decimal value)
{
    decimal wholePart = Math.Truncate(value);
    if (value == wholePart)
    {
        if (sbyte.MinValue <= wholePart && wholePart <= sbyte.MaxValue)
            return (sbyte)wholePart;
        if (byte.MinValue <= wholePart && wholePart <= byte.MaxValue)
            return (byte)wholePart;
        if (short.MinValue <= wholePart && wholePart <= short.MaxValue)
            return (short)wholePart;
        if (ushort.MinValue <= wholePart && wholePart <= ushort.MaxValue)
            return (ushort)wholePart;
        if (int.MinValue <= wholePart && wholePart <= int.MaxValue)
            return (int)wholePart;
        if (uint.MinValue <= wholePart && wholePart <= uint.MaxValue)
            return (uint)wholePart;
        if (long.MinValue <= wholePart && wholePart <= long.MaxValue)
            return (long)wholePart;
        if (ulong.MinValue <= wholePart && wholePart <= ulong.MaxValue)
            return (ulong)wholePart;
    }
    else
    {
        var strValue = value.ToString();
        float f;
        if (float.TryParse(strValue, out f))
            return f;
        double d;
        if (double.TryParse(strValue, out d))
            return d;
    }
    return value;
}

Upvotes: 1

Stecya
Stecya

Reputation: 23266

you can try to use TryParse

        short res;
        decimal value = 8913798132;
        bool s = short.TryParse(value.ToString(), out res); // returns false

Upvotes: 2

Related Questions