Выполнение математических операций над типом десятичных данных в C #? - PullRequest
17 голосов
/ 08 ноября 2010

Мне было интересно, возможно ли вышесказанное вообще.Например:

Math.Sqrt(myVariableHere);

При рассмотрении перегрузки требуется двойной параметр, поэтому я не уверен, есть ли другой способ повторить это с десятичными типами данных.

Ответы [ 5 ]

52 голосов
/ 20 июля 2011

Я не понимаю, почему все ответы на этот вопрос одинаковы.

Есть несколько способов вычислить квадратный корень из числа. Один из них был предложен Исааком Ньютоном. Я напишу только одну из самых простых реализаций этого метода. Я использую его для повышения точности двойного квадратного корня.

// 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;
}

О скорости: в худшем случае (epsilon = 0 и число десятичное. MaxValue) цикл повторяется менее трех раз.

Если вы хотите узнать больше, прочитайте это ( Восторг Хакера Генри Уоррена, младшего)

4 голосов
/ 08 ноября 2012

Я только что натолкнулся на этот вопрос, и я бы предложил другой алгоритм, чем тот, который предложил SLenik.Он основан на вавилонском методе .

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);
}

. Он не требует использования существующей функции Sqrt и, таким образом, позволяет избежать преобразования в double и обратно вместе с сопровождающим.потеря точности.

4 голосов
/ 08 ноября 2010

В большинстве случаев с decimal (валютой и т. Д.) бесполезно получать root;и корень не будет иметь ничего, как ожидаемая точность, которую вы могли бы ожидать от decimal.Вы, конечно, можете форсировать его, используя приведение (при условии, что мы не имеем дело с экстремальными концами диапазона decimal):

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

, что вынуждает вас хотя бы признать присущие им проблемы округления.

0 голосов
/ 08 ноября 2010
Math.Sqrt((double)myVariableHere);

Вернет вам двойной квадрат, который является квадратным корнем из вашего decimal myVariableHere.

0 голосов
/ 08 ноября 2010

Простой: приведите decimal к double и вызовите функцию, получите результат и приведите его к decimal.Вероятно, это будет быстрее, чем любая функция sqrt, которую вы можете выполнить самостоятельно, и сэкономит много усилий.

...