Performing Math operations on decimal datatype in C#?

前端 未结 5 1109
情深已故
情深已故 2020-11-30 07:27

I was wondering if the above was at all possible. For example:

Math.Sqrt(myVariableHere);

When looking at the overload, it requires a doub

相关标签:
5条回答
  • 2020-11-30 08:07

    I don't understand why all the answers to that question are the same.

    There are several ways to calculate the square root from a number. One of them was proposed by Isaac Newton. I'll only write one of the simplest implementations of this method. I use it to improve the accuracy of double's square root.

    // x - a number, from which we need to calculate the square root
    // epsilon - an accuracy of calculation of the root from our number.
    // The result of the calculations will differ from an actual value
    // of the root on less than epslion.
    public static decimal Sqrt(decimal x, decimal epsilon = 0.0M)
    {
        if (x < 0) throw new OverflowException("Cannot calculate square root from a negative number");
    
        decimal current = (decimal)Math.Sqrt((double)x), previous;
        do
        {
            previous = current;
            if (previous == 0.0M) return 0;
            current = (previous + x / previous) / 2;
        }
        while (Math.Abs(previous - current) > epsilon);
        return current;
    }
    

    About speed: in the worst case (epsilon = 0 and number is decimal.MaxValue) the loop repeats less than a three times.

    If you want to know more, read this (Hacker's Delight by Henry S. Warren, Jr.)

    0 讨论(0)
  • 2020-11-30 08:16

    Simple: Cast your decimal to a double and call the function, get the result and cast that back to a decimal. That will probably be faster than any sqrt function you could make on your own, and save a lot of effort.

    0 讨论(0)
  • 2020-11-30 08:20
    Math.Sqrt((double)myVariableHere);
    

    Will give you back a double that's the square root of your decimal myVariableHere.

    0 讨论(0)
  • 2020-11-30 08:22

    I just came across this question, and I'd suggest a different algorithm than the one SLenik proposed. This is based on the Babylonian Method.

    public static decimal Sqrt(decimal x, decimal? guess = null)
    {
        var ourGuess = guess.GetValueOrDefault(x / 2m);
        var result = x / ourGuess;
        var average = (ourGuess + result) / 2m;
    
        if (average == ourGuess) // This checks for the maximum precision possible with a decimal.
            return average;
        else
            return Sqrt(x, average);
    }
    

    It doesn't require using the existing Sqrt function, and thus avoids converting to double and back, with the accompanying loss of precision.

    0 讨论(0)
  • 2020-11-30 08:28

    In most cases involving a decimal (currency etc), it isn't useful to take a root; and the root won't have anything like the expected precision that you might expect a decimal to have. You can of course force it by casting (assuming we aren't dealing with extreme ends of the decimal range):

    decimal root = (decimal)Math.Sqrt((double)myVariableHere);
    

    which forces you to at least acknowledge the inherent rounding issues.

    0 讨论(0)
提交回复
热议问题