本文整理汇总了C#中BigDecimal.ScaleByPowerOfTen方法的典型用法代码示例。如果您正苦于以下问题:C# BigDecimal.ScaleByPowerOfTen方法的具体用法?C# BigDecimal.ScaleByPowerOfTen怎么用?C# BigDecimal.ScaleByPowerOfTen使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类BigDecimal
的用法示例。
在下文中一共展示了BigDecimal.ScaleByPowerOfTen方法的1个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: Exp
public static BigDecimal Exp(BigDecimal x)
{
/* To calculate the value if x is negative, use exp(-x) = 1/exp(x)
*/
if (x.CompareTo(BigDecimal.Zero) < 0) {
BigDecimal invx = Exp(x.Negate());
/* Relative error in inverse of invx is the same as the relative errror in invx.
* This is used to define the precision of the result.
*/
var mc = new MathContext(invx.Precision);
return BigDecimal.One.Divide(invx, mc);
}
if (x.CompareTo(BigDecimal.Zero) == 0) {
/* recover the valid number of digits from x.ulp(), if x hits the
* zero. The x.precision() is 1 then, and does not provide this information.
*/
return ScalePrecision(BigDecimal.One, -(int) (System.Math.Log10(x.Ulp().ToDouble())));
}
/* Push the number in the Taylor expansion down to a small
* value where TAYLOR_NTERM terms will do. If x<1, the n-th term is of the order
* x^n/n!, and equal to both the absolute and relative error of the result
* since the result is close to 1. The x.ulp() sets the relative and absolute error
* of the result, as estimated from the first Taylor term.
* We want x^TAYLOR_NTERM/TAYLOR_NTERM! < x.ulp, which is guaranteed if
* x^TAYLOR_NTERM < TAYLOR_NTERM*(TAYLOR_NTERM-1)*...*x.ulp.
*/
double xDbl = x.ToDouble();
double xUlpDbl = x.Ulp().ToDouble();
if (System.Math.Pow(xDbl, TaylorNterm) < TaylorNterm*(TaylorNterm - 1.0)*(TaylorNterm - 2.0)*xUlpDbl) {
/* Add TAYLOR_NTERM terms of the Taylor expansion (Euler's sum formula)
*/
BigDecimal resul = BigDecimal.One;
/* x^i */
BigDecimal xpowi = BigDecimal.One;
/* i factorial */
BigInteger ifac = BigInteger.One;
/* TAYLOR_NTERM terms to be added means we move x.ulp() to the right
* for each power of 10 in TAYLOR_NTERM, so the addition won't add noise beyond
* what's already in x.
*/
var mcTay = new MathContext(ErrorToPrecision(1d, xUlpDbl/TaylorNterm));
for (int i = 1; i <= TaylorNterm; i++) {
ifac = ifac.Multiply(BigInteger.ValueOf(i));
xpowi = xpowi.Multiply(x);
BigDecimal c = xpowi.Divide(new BigDecimal(ifac), mcTay);
resul = resul.Add(c);
if (System.Math.Abs(xpowi.ToDouble()) < i &&
System.Math.Abs(c.ToDouble()) < 0.5*xUlpDbl)
break;
}
/* exp(x+deltax) = exp(x)(1+deltax) if deltax is <<1. So the relative error
* in the result equals the absolute error in the argument.
*/
var mc = new MathContext(ErrorToPrecision(xUlpDbl/2d));
return resul.Round(mc);
} else {
/* Compute exp(x) = (exp(0.1*x))^10. Division by 10 does not lead
* to loss of accuracy.
*/
var exSc = (int) (1.0 - System.Math.Log10(TaylorNterm*(TaylorNterm - 1.0)*(TaylorNterm - 2.0)*xUlpDbl
/System.Math.Pow(xDbl, TaylorNterm))/(TaylorNterm - 1.0));
BigDecimal xby10 = x.ScaleByPowerOfTen(-exSc);
BigDecimal expxby10 = Exp(xby10);
/* Final powering by 10 means that the relative error of the result
* is 10 times the relative error of the base (First order binomial expansion).
* This looses one digit.
*/
var mc = new MathContext(expxby10.Precision - exSc);
/* Rescaling the powers of 10 is done in chunks of a maximum of 8 to avoid an invalid operation
* response by the BigDecimal.pow library or integer overflow.
*/
while (exSc > 0) {
int exsub = System.Math.Min(8, exSc);
exSc -= exsub;
var mctmp = new MathContext(expxby10.Precision - exsub + 2);
int pex = 1;
while (exsub-- > 0)
pex *= 10;
expxby10 = expxby10.Pow(pex, mctmp);
}
return expxby10.Round(mc);
}
}