John NoCookies
John NoCookies

Reputation: 1061

A way of writing large numeral literals in C#

I have a method like this:

Prefix GetPrefix(decimal value)
{
    if(value > 11000000000000000000)
        return Prefix.CosmicBig;
    if(value > 1000000000000000)
        return Prefix.ReallyBig;
    if(value > 3000000000000)
        return Prefix.Big;
    if(value > 50000000)
        return Prefix.Okay;
    if(value > 750000)
        return Prefix.MostlyNormal;
    if(value > 750000)
        return Prefix.SoSo;
    if(value > 750)
        return Prefix.Small;
    return Prefix.MiserablySmall;
}

The exact values are not important. What matters is that they are sometimes changed (the prefixes are used for drawing and some text areas change sizes in development). I'm looking for a way of writing these literals in a way that's easily readably by a human changing it, without having to count all the zeroes. A separator would be nice. I thought about writing 11 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000, but that's only barely more manageable. Using Math.Pow() does it a little better, but I'm not comfortable with using such calculations to define constants.

Upvotes: 6

Views: 2595

Answers (3)

Jesus
Jesus

Reputation: 11

A language feature introduced on C# 7.0 is the introduction of _ as a digit separator when inside number literals, so instead of 50000000 you can write 50_000_000.

https://devblogs.microsoft.com/dotnet/new-features-in-c-7-0/#literal-improvements

For very large numbers, or if working with numbers in scientific notation, the solution given by Sjoerd might be a better option.

Upvotes: 1

Daniel Hilgarth
Daniel Hilgarth

Reputation: 174397

You can introduce extension methods for int:

750.Thousand();
5.Million();
100.Billion();

The implementation of these methods is simple:

public static int Thousand(this int value)
{
    return value * 1000;
}

public static int Million(this int value)
{
    return value.Thousand() * 1000;
}

// etc.

Make sure to return the appropriate data type for methods for bigger numbers:

public static long Billion(this int value)
{
    return value.Million() * 1000;
}

Unfortunatelly, you will have to write those methods for every integral or floating point type you want to support.

Having a full set of such extension methods would allow you to express your large numbers in relativly natural ways, even when it's not just all zeros at the end:

100.Billion() + 30.Thousand() + 300 // == 100,000,030,300

If you want to get fancy, you could even think about nesting them:

100.Billion(30.Thousand(300))

But I think that would lose some expressiveness, because people would wonder what the parameter means.

Still, implementation would look like this:

public static long Billion(this int value, long add)
{
    return value.Million() * 1000 + add;
}

Using these extension methods has one little downside: Your numbers are no longer compile-time constants. They are calculated at runtime. In the vast majority of cases, this shouldn't be a problem.

Upvotes: 15

Sjoerd
Sjoerd

Reputation: 75629

Instead of 11000000000000000000 you can use 11e18. Use m to indicate that it is a decimal, so 11e18m.

Upvotes: 23

Related Questions