/// <summary> /// 自然対数のテーラー展開。 /// ln(input) = ln 2^count2 (1+x) ≒ count2 * ln2 + (x - x^2/2 + x^3/3 - x^4/4 + ・・・) /// </summary> /// <param name="input"></param> /// <returns></returns> public static decimal NaturalLogarithm(decimal input) { //引数が0以下が定義できないので、例外を返す if (input <= 0) { throw new FormatException("Input " + nameof(input) + ";" + input.ToString("G6") + "must be equal to or more than zero"); } //引数が1より小さい場合、絶対値の大きな負の数が返される。 //近似の制度が下がるので、ln(input) = -ln(1/input)=-ln(1+x) //とおいて計算する。 decimal onePlusX = input; decimal sign = 1m; if (input < 1) { onePlusX = 1m / input; sign = -1; } //input = 2^count2 * (1+x) //の形に変形する。 uint count2 = 0; while (onePlusX > 2m) { count2++; onePlusX /= 2m; } decimal x = onePlusX - 1m; decimal numerator = x; decimal result = count2 * TaylorSeriesDecimal.Ln2(); //テーラー展開 result += x; for (int j = 2; j <= (int)Math.Ceiling(10m * x); j++) { numerator *= x; if (j % 2 == 0) { result -= numerator / j; } else { result += numerator / j; } } //符号を反映する. result *= sign; return(result); }
public decimal Calculate_f_u(decimal[] input) { decimal index = 0.0m; for (int j = 0; j < input.Length; j++) { index += input[j] * input[j]; } return(TaylorSeriesDecimal.Exponential(-index / 2m)); }
/// <summary> /// 平方根のテーラー展開。 /// √input = √2^count2 * (1+x) = √2^count2 * ( 1 + x/2 - x^2/8 + x^3/16 - x^4/128 + ・・・) /// </summary> /// <param name="input"></param> /// <returns></returns> public static decimal SquareRoot(decimal input) { if (input == 0m) { return(decimal.Zero); } else if (input < 0) { throw new FormatException("Input " + nameof(input) + ";" + input.ToString("G6") + "must be equal to or more than zero ."); } //input = 2^count2 * (1+x) //の形に変形する。 decimal onePlusX = input; if (input < 1) { onePlusX = 1m / input; } uint count2 = 0; while (onePlusX > 2m) { count2++; onePlusX /= 2m; } decimal x = onePlusX - 1m; //テーラー展開 decimal numerator = x; decimal result = 1m + x / 2m; numerator *= x; result -= numerator / 8m; numerator *= x; result += numerator / 16m; numerator *= x; result -= numerator / 128m; //√2^count2 をかける for (uint j = 0; j < count2 / 2; j++) { result *= 2m; } for (uint j = 0; j < count2 / 2 - 1; j++) { result *= TaylorSeriesDecimal.Sqrt2(); } return(result); }
/// <summary> /// 乱数を生成する /// 平均値 average /// 標準偏差 std /// </summary> /// <param name="average"></param> /// <param name="std"></param> /// <returns></returns> public decimal NextDecimal(decimal average, decimal std) { retry_point: decimal u1 = ud1.NextDecimal(); decimal u2 = ud2.NextDecimal(); decimal v1 = 2 * u1 - 1; decimal v2 = 2 * u2 - 1; decimal v = v1 * v1 + v2 * v2; if (v <= 0 || 1 <= v) { goto retry_point; } decimal w = TaylorSeriesDecimal.SquareRoot(-2 * TaylorSeriesDecimal.NaturalLogarithm(v) / v); decimal y1 = v1 * w; decimal y2 = v2 * w; if (even) { resultDecimal = y1; even = false; } else { resultDecimal = y2; even = true; } resultDecimal = TaylorSeriesDecimal.Exponential(resultDecimal * Math.Abs(std) + average); return(resultDecimal); }