Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I round doubles in human-friendly manner in C#?

In my C# program I have a double obtained from some computation and its value is something like 0,13999 or 0,0079996 but this value has to be presented to a human so it's better displayed as 0,14 or 0,008 respectively.

So I need to round the value, but have no idea to which precision - I just need to "throw away those noise digits".

How could I do that in my code?

To clarify - I need to round the double values to a precision that is unknown at compile time - this needs to be determined at runtime. What would be a good heuristic to achieve this?

like image 249
sharptooth Avatar asked Jan 01 '26 11:01

sharptooth


2 Answers

You seem to want to output a value which is not very different to the input value, so try increasing numbers of digits until a given error is achieved:

    static double Round(double input, double errorDesired)
    {
        if (input == 0.0) 
            return 0.0;

        for (int decimals = 0; decimals < 17; ++decimals)
        {
            var output = Math.Round(input, decimals);
            var errorAchieved = Math.Abs((output - input) / input);

            if (errorAchieved <= errorDesired)
                return output;
        }

        return input;
    }
}


    static void Main(string[] args)
    {
        foreach (var input in new[] { 0.13999, 0.0079996, 0.12345 })
        {
            Console.WriteLine("{0} -> {1}         (.1%)", input, Round(input, 0.001));
            Console.WriteLine("{0} -> {1}         (1%)", input, Round(input, 0.01));
            Console.WriteLine("{0} -> {1}         (10%)", input, Round(input, 0.1));
        }
    }
like image 107
Pete Kirkham Avatar answered Jan 02 '26 23:01

Pete Kirkham


private double PrettyRound(double inp)
{
    string d = inp.ToString();
    d = d.Remove(0,d.IndexOf(',') + 1);
    int decRound = 1;
    bool onStartZeroes = true;
    for (int c = 1; c < d.Length; c++ )
    {
        if (!onStartZeroes && d[c] == d[c - 1])
            break;
        else
            decRound++;
        if (d[c] != '0')
            onStartZeroes = false;
    }

    inp = Math.Round(inp, decRound);
    return inp;
}

Test:

    double d1 = 0.13999; //no zeroes
    double d2 = 0.0079996; //zeroes
    double d3 = 0.00700956; //zeroes within decimal

    Response.Write(d1 + "<br/>" + d2 + "<br/>" + d3 + "<br/><br/>");

    d1 = PrettyRound(d1);
    d2 = PrettyRound(d2);
    d3 = PrettyRound(d3);

    Response.Write(d1 + "<br/>" + d2 + "<br/>" + d3 +"<br/><br/>");

Prints:

0,13999
0,0079996
0,00700956

0,14
0,008
0,007

Rounds your numbers as you wrote in your example..

like image 41
f2lollpll Avatar answered Jan 03 '26 00:01

f2lollpll



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!