上記は可能かと思っていました。例えば:
Math.Sqrt(myVariableHere);
オーバーロードを見ると、doubleパラメーターが必要なので、10進数のデータ型でこれを複製する別の方法があるかどうかはわかりません。
decimal
(通貨など)が関係するほとんどの場合、ルートを取ることは便利ではありません。また、ルートには、decimal
に期待されるような期待される精度はありません。もちろん、キャストすることで強制することができます(decimal
範囲の極端な端を扱っていないと仮定します):
decimal root = (decimal)Math.Sqrt((double)myVariableHere);
これにより、少なくとも固有の丸めの問題を認識する必要があります。
その質問に対するすべての答えが同じである理由がわかりません。
数値から平方根を計算する方法はいくつかあります。それらの1つはアイザックニュートンによって提案されました。このメソッドの最も単純な実装の1つだけを記述します。ダブルの平方根の精度を上げるために使用します。
// 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、数値はdecimal.MaxValue)、ループの繰り返しは3回未満です。
詳細を知りたい場合は、 this(Hacker's Delightby Henry S. Warren、Jr。) をお読みください。
私はちょうどこの質問に出くわしました、そして私は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
への変換とその逆の変換が回避され、精度が低下します。