I am trying to convert a C++ class to C# and in the process learn something of C++. I had never run into a vector<> before and my understanding is this is like a List<> function in C#. During the conversion of the class I re-wrote the code using List futures_price = New List(Convert.ToInt32(no_steps) + 1);. As soon as I run the code, I get a "Index was out of range" error.
Having looked around on SOF, I believe the issue is regarding the parameter being out of index range relating to this, but I do not see a simple solution to solve this with the below code.
In particular, this is the line that is triggering the error: futures_prices[0] = spot_price * Math.Pow(d, no_steps);
Below is the full code:
public double futures_option_price_call_american_binomial(double spot_price, double option_strike, double r, double sigma, double time, double no_steps)
{
//double spot_price, // price futures contract
//double option_strike, // exercise price
//double r, // interest rate
//double sigma, // volatility
//double time, // time to maturity
//int no_steps
List<double> futures_prices = new List<double>(Convert.ToInt32(no_steps) + 1);
//(no_steps+1);
//double call_values = (no_steps+1);
List<double> call_values = new List<double>(Convert.ToInt32(no_steps) + 1);
double t_delta = time/no_steps;
double Rinv = Math.Exp(-r*(t_delta));
double u = Math.Exp(sigma * Math.Sqrt(t_delta));
double d = 1.0/u;
double uu= u*u;
double pUp = (1-d)/(u-d); // note how probability is calculated
double pDown = 1.0 - pUp;
futures_prices[0] = spot_price * Math.Pow(d, no_steps);
int i;
for (i=1; i<=no_steps; ++i) futures_prices[i] = uu*futures_prices[i-1]; // terminal tree nodes
for (i=0; i<=no_steps; ++i) call_values[i] = Math.Max(0.0, (futures_prices[i]-option_strike));
for (int step = Convert.ToInt32(no_steps) - 1; step >= 0; --step)
{
for (i = 0; i <= step; ++i)
{
futures_prices[i] = d * futures_prices[i + 1];
call_values[i] = (pDown * call_values[i] + pUp * call_values[i + 1]) * Rinv;
call_values[i] = Math.Max(call_values[i], futures_prices[i] - option_strike); // check for exercise
};
};
return call_values[0];
}
Here is the original source in C++:
double futures_option_price_call_american_binomial(const double& F, // price futures contract
const double& K, // exercise price
const double& r, // interest rate
const double& sigma, // volatility
const double& time, // time to maturity
const int& no_steps) { // number of steps
vector<double> futures_prices(no_steps+1);
vector<double> call_values (no_steps+1);
double t_delta= time/no_steps;
double Rinv = exp(-r*(t_delta));
double u = exp(sigma*sqrt(t_delta));
double d = 1.0/u;
double uu= u*u;
double pUp = (1-d)/(u-d); // note how probability is calculated
double pDown = 1.0 - pUp;
futures_prices[0] = F*pow(d, no_steps);
int i;
for (i=1; i<=no_steps; ++i) futures_prices[i] = uu*futures_prices[i-1]; // terminal tree nodes
for (i=0; i<=no_steps; ++i) call_values[i] = max(0.0, (futures_prices[i]-K));
for (int step=no_steps-1; step>=0; --step) {
for (i=0; i<=step; ++i) {
futures_prices[i] = d*futures_prices[i+1];
call_values[i] = (pDown*call_values[i]+pUp*call_values[i+1])*Rinv;
call_values[i] = max(call_values[i], futures_prices[i]-K); // check for exercise
};
};
return call_values[0];
};
A List<double> starts out empty until you add items to it. (passing the constructor argument just sets the capacity, preventing costly resizes)
You can't access [0] until you Add() it.
To use it the way you are, use an array instead.
As SLaks says, it's better to use an Array in this situation. C# lists are filled with Add method and values are removed through Remove method... this would be more complicated and memory/performance expensive as you are also replacing values.
public Double FuturesOptionPriceCallAmericanBinomial(Double spotPrice, Double optionStrike, Double r, Double sigma, Double time, Double steps)
{
// Avoid calling Convert multiple times as it can be quite performance expensive.
Int32 stepsInteger = Convert.ToInt32(steps);
Double[] futurePrices = new Double[(stepsInteger + 1)];
Double[] callValues = new Double[(stepsInteger + 1)];
Double tDelta = time / steps;
Double rInv = Math.Exp(-r * (tDelta));
Double u = Math.Exp(sigma * Math.Sqrt(tDelta));
Double d = 1.0 / u;
Double uu = u * u;
Double pUp = (1 - d) / (u - d);
Double pDown = 1.0 - pUp;
futurePrices[0] = spotPrice * Math.Pow(d, steps);
for (Int32 i = 1; i <= steps; ++i)
futurePrices[i] = uu * futurePrices[(i - 1)];
for (Int32 i = 0; i <= steps; ++i)
callValues[i] = Math.Max(0.0, (futurePrices[i] - optionStrike));
for (Int32 step = stepsInteger - 1; step >= 0; --step)
{
for (Int32 i = 0; i <= step; ++i)
{
futurePrices[i] = d * futurePrices[(i + 1)];
callValues[i] = ((pDown * callValues[i]) + (pUp * callValues[i + 1])) * rInv;
callValues[i] = Math.Max(callValues[i], (futurePrices[i] - option_strike));
}
}
return callValues[0];
}
Related
The code below somewhat works but not rounding correctly, my goal is if a value = 1.5 round down, if 1.51 round up.
Thanks
if (!String.IsNullOrEmpty(tbSnp_Uld.Text) && !string.IsNullOrEmpty(cbSnp_Uld.Text))
{
double d_tbSnp_Uld = Convert.ToDouble(tbSnp_Uld.Text);
double d_cbSnp_Uld = Convert.ToDouble(cbSnp_Uld.Text);
double result1 = Math.Ceiling(d_tbSnp_Uld / d_cbSnp_Uld);
double d = 0;
int floored = (int)Math.Floor(d);
int ceiled = (int)Math.Ceiling(d);
double epsilon = 0;
int lessThan = floored - Convert.ToInt32(Math.Abs(d - floored) < epsilon);
int moreThan = ceiled + Convert.ToInt32(Math.Abs(d - ceiled) < epsilon);
tbTrailer_Needed.Text = result1.ToString();
}
Here raw sample of what you trying to accomplish. Wrote this by using TDD apporach: add tests -> make it pass.
So feel free to refactor it
public static int CustomRound(double value)
{
int sign = Math.Sign(value);
double absValue = Math.Abs(value);
int absResult = (int)Math.Round(absValue - 0.01, 0, MidpointRounding.AwayFromZero);
return absResult * sign;
}
how to find the min and max for quadratic equation using c# ??
f(x,y) = x^2 + y^2 + 25 * (sin(x)^2 + sin(y)^2) ,where (x,y) from (-2Pi, 2Pi) ??
in the manual solving I got min is = 0 , max = 8Pi^2 = 78.957 .
I tried to write the code based on liner quadratic code but something goes totally wrong
this code give the min = -4.?? and the max = 96 could you help to know where is my mistake please ??
I uploaded the code to dropbox if anyone can have look : https://www.dropbox.com/s/p7y6krk2gk29i9e/Program.cs
double[] X, Y, Result; // Range array and result array.
private void BtnRun_Click(object sender, EventArgs e)
{
//Set any Range for the function
X = setRange(-2 * Math.PI, 2 * Math.PI, 10000);
Y = setRange(-2 * Math.PI, 2 * Math.PI, 10000);
Result = getOutput_twoVariablesFunction(X, Y);
int MaxIndex = getMaxIndex(Result);
int MinIndex = getMinIndex(Result);
TxtMin.Text = Result[MinIndex].ToString();
TxtMax.Text = Result[MaxIndex].ToString();
}
private double twoVariablesFunction(double x,double y)
{
double f;
//Set any two variables function
f = Math.Pow(x, 2) + Math.Pow(y, 2) + 25 * (Math.Pow(Math.Sin(x), 2) + Math.Pow(Math.Sin(y), 2));
return f;
}
private double[] setRange(double Start, double End, int Sample)
{
double Step = (End - Start) / Sample;
double CurrentVaue = Start;
double[] Array = new double[Sample];
for (int Index = 0; Index < Sample; Index++)
{
Array[Index] = CurrentVaue;
CurrentVaue += Step;
}
return Array;
}
private double[] getOutput_twoVariablesFunction(double[] X, double[] Y)
{
int Step = X.Length;
double[] Array = new double[Step];
for (int Index = 0; Index < X.Length ; Index++)
{
Array[Index] = twoVariablesFunction(X[Index], Y[Index]);
}
return Array;
}
private int getMaxIndex(double[] ValuesArray)
{
double M = ValuesArray.Max();
int Index = ValuesArray.ToList().IndexOf(M);
return Index;
}
private int getMinIndex(double[] ValuesArray)
{
double M = ValuesArray.Min();
int Index = ValuesArray.ToList().IndexOf(M);
return Index;
}
Do you want to compute (sin(x))^2 or sin(x^2)? In your f(x,y) formula it looks like (sin(x))^2, but in your method twoVariablesFunction like sin(x^2).
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed last year.
Improve this question
Do you know of a .net library to perform a LOESS/LOWESS regression? (preferably free/open source)
Port from java to c#
public class LoessInterpolator
{
public static double DEFAULT_BANDWIDTH = 0.3;
public static int DEFAULT_ROBUSTNESS_ITERS = 2;
/**
* The bandwidth parameter: when computing the loess fit at
* a particular point, this fraction of source points closest
* to the current point is taken into account for computing
* a least-squares regression.
*
* A sensible value is usually 0.25 to 0.5.
*/
private double bandwidth;
/**
* The number of robustness iterations parameter: this many
* robustness iterations are done.
*
* A sensible value is usually 0 (just the initial fit without any
* robustness iterations) to 4.
*/
private int robustnessIters;
public LoessInterpolator()
{
this.bandwidth = DEFAULT_BANDWIDTH;
this.robustnessIters = DEFAULT_ROBUSTNESS_ITERS;
}
public LoessInterpolator(double bandwidth, int robustnessIters)
{
if (bandwidth < 0 || bandwidth > 1)
{
throw new ApplicationException(string.Format("bandwidth must be in the interval [0,1], but got {0}", bandwidth));
}
this.bandwidth = bandwidth;
if (robustnessIters < 0)
{
throw new ApplicationException(string.Format("the number of robustness iterations must be non-negative, but got {0}", robustnessIters));
}
this.robustnessIters = robustnessIters;
}
/**
* Compute a loess fit on the data at the original abscissae.
*
* #param xval the arguments for the interpolation points
* #param yval the values for the interpolation points
* #return values of the loess fit at corresponding original abscissae
* #throws MathException if some of the following conditions are false:
* <ul>
* <li> Arguments and values are of the same size that is greater than zero</li>
* <li> The arguments are in a strictly increasing order</li>
* <li> All arguments and values are finite real numbers</li>
* </ul>
*/
public double[] smooth(double[] xval, double[] yval)
{
if (xval.Length != yval.Length)
{
throw new ApplicationException(string.Format("Loess expects the abscissa and ordinate arrays to be of the same size, but got {0} abscisssae and {1} ordinatae", xval.Length, yval.Length));
}
int n = xval.Length;
if (n == 0)
{
throw new ApplicationException("Loess expects at least 1 point");
}
checkAllFiniteReal(xval, true);
checkAllFiniteReal(yval, false);
checkStrictlyIncreasing(xval);
if (n == 1)
{
return new double[] { yval[0] };
}
if (n == 2)
{
return new double[] { yval[0], yval[1] };
}
int bandwidthInPoints = (int)(bandwidth * n);
if (bandwidthInPoints < 2)
{
throw new ApplicationException(string.Format("the bandwidth must be large enough to accomodate at least 2 points. There are {0} " +
" data points, and bandwidth must be at least {1} but it is only {2}",
n, 2.0 / n, bandwidth
));
}
double[] res = new double[n];
double[] residuals = new double[n];
double[] sortedResiduals = new double[n];
double[] robustnessWeights = new double[n];
// Do an initial fit and 'robustnessIters' robustness iterations.
// This is equivalent to doing 'robustnessIters+1' robustness iterations
// starting with all robustness weights set to 1.
for (int i = 0; i < robustnessWeights.Length; i++) robustnessWeights[i] = 1;
for (int iter = 0; iter <= robustnessIters; ++iter)
{
int[] bandwidthInterval = { 0, bandwidthInPoints - 1 };
// At each x, compute a local weighted linear regression
for (int i = 0; i < n; ++i)
{
double x = xval[i];
// Find out the interval of source points on which
// a regression is to be made.
if (i > 0)
{
updateBandwidthInterval(xval, i, bandwidthInterval);
}
int ileft = bandwidthInterval[0];
int iright = bandwidthInterval[1];
// Compute the point of the bandwidth interval that is
// farthest from x
int edge;
if (xval[i] - xval[ileft] > xval[iright] - xval[i])
{
edge = ileft;
}
else
{
edge = iright;
}
// Compute a least-squares linear fit weighted by
// the product of robustness weights and the tricube
// weight function.
// See http://en.wikipedia.org/wiki/Linear_regression
// (section "Univariate linear case")
// and http://en.wikipedia.org/wiki/Weighted_least_squares
// (section "Weighted least squares")
double sumWeights = 0;
double sumX = 0, sumXSquared = 0, sumY = 0, sumXY = 0;
double denom = Math.Abs(1.0 / (xval[edge] - x));
for (int k = ileft; k <= iright; ++k)
{
double xk = xval[k];
double yk = yval[k];
double dist;
if (k < i)
{
dist = (x - xk);
}
else
{
dist = (xk - x);
}
double w = tricube(dist * denom) * robustnessWeights[k];
double xkw = xk * w;
sumWeights += w;
sumX += xkw;
sumXSquared += xk * xkw;
sumY += yk * w;
sumXY += yk * xkw;
}
double meanX = sumX / sumWeights;
double meanY = sumY / sumWeights;
double meanXY = sumXY / sumWeights;
double meanXSquared = sumXSquared / sumWeights;
double beta;
if (meanXSquared == meanX * meanX)
{
beta = 0;
}
else
{
beta = (meanXY - meanX * meanY) / (meanXSquared - meanX * meanX);
}
double alpha = meanY - beta * meanX;
res[i] = beta * x + alpha;
residuals[i] = Math.Abs(yval[i] - res[i]);
}
// No need to recompute the robustness weights at the last
// iteration, they won't be needed anymore
if (iter == robustnessIters)
{
break;
}
// Recompute the robustness weights.
// Find the median residual.
// An arraycopy and a sort are completely tractable here,
// because the preceding loop is a lot more expensive
System.Array.Copy(residuals, sortedResiduals, n);
//System.arraycopy(residuals, 0, sortedResiduals, 0, n);
Array.Sort<double>(sortedResiduals);
double medianResidual = sortedResiduals[n / 2];
if (medianResidual == 0)
{
break;
}
for (int i = 0; i < n; ++i)
{
double arg = residuals[i] / (6 * medianResidual);
robustnessWeights[i] = (arg >= 1) ? 0 : Math.Pow(1 - arg * arg, 2);
}
}
return res;
}
/**
* Given an index interval into xval that embraces a certain number of
* points closest to xval[i-1], update the interval so that it embraces
* the same number of points closest to xval[i]
*
* #param xval arguments array
* #param i the index around which the new interval should be computed
* #param bandwidthInterval a two-element array {left, right} such that: <p/>
* <tt>(left==0 or xval[i] - xval[left-1] > xval[right] - xval[i])</tt>
* <p/> and also <p/>
* <tt>(right==xval.length-1 or xval[right+1] - xval[i] > xval[i] - xval[left])</tt>.
* The array will be updated.
*/
private static void updateBandwidthInterval(double[] xval, int i, int[] bandwidthInterval)
{
int left = bandwidthInterval[0];
int right = bandwidthInterval[1];
// The right edge should be adjusted if the next point to the right
// is closer to xval[i] than the leftmost point of the current interval
int nextRight = nextNonzero(weights, right);
if (nextRight < xval.Length && xval[nextRight] - xval[i] < xval[i] - xval[left])
{
int nextLeft = nextNonzero(weights, bandwidthInterval[0]);
bandwidthInterval[0] = nextLeft;
bandwidthInterval[1] = nextRight;
}
}
/**
* Compute the
* tricube
* weight function
*
* #param x the argument
* #return (1-|x|^3)^3
*/
private static double tricube(double x)
{
double tmp = Math.abs(x);
tmp = 1 - tmp * tmp * tmp;
return tmp * tmp * tmp;
}
/**
* Check that all elements of an array are finite real numbers.
*
* #param values the values array
* #param isAbscissae if true, elements are abscissae otherwise they are ordinatae
* #throws MathException if one of the values is not
* a finite real number
*/
private static void checkAllFiniteReal(double[] values, bool isAbscissae)
{
for (int i = 0; i < values.Length; i++)
{
double x = values[i];
if (Double.IsInfinity(x) || Double.IsNaN(x))
{
string pattern = isAbscissae ?
"all abscissae must be finite real numbers, but {0}-th is {1}" :
"all ordinatae must be finite real numbers, but {0}-th is {1}";
throw new ApplicationException(string.Format(pattern, i, x));
}
}
}
/**
* Check that elements of the abscissae array are in a strictly
* increasing order.
*
* #param xval the abscissae array
* #throws MathException if the abscissae array
* is not in a strictly increasing order
*/
private static void checkStrictlyIncreasing(double[] xval)
{
for (int i = 0; i < xval.Length; ++i)
{
if (i >= 1 && xval[i - 1] >= xval[i])
{
throw new ApplicationException(string.Format(
"the abscissae array must be sorted in a strictly " +
"increasing order, but the {0}-th element is {1} " +
"whereas {2}-th is {3}",
i - 1, xval[i - 1], i, xval[i]));
}
}
}
}
Since I'm unable to comment on other people's posts (new user), and people seem to think I should do that with this instead of editing the above answer, I'm simply going to write it as an answer even though I know this is better as a comment.
The updateBandwidthInterval method in the above answer forgets to check the left side as written in the method comment. This can give NaN issues for sumWeights. The below should fix that. I encountered this when doing a c++ implementation based on the above.
/**
* Given an index interval into xval that embraces a certain number of
* points closest to xval[i-1], update the interval so that it embraces
* the same number of points closest to xval[i]
*
* #param xval arguments array
* #param i the index around which the new interval should be computed
* #param bandwidthInterval a two-element array {left, right} such that: <p/>
* <tt>(left==0 or xval[i] - xval[left-1] > xval[right] - xval[i])</tt>
* <p/> and also <p/>
* <tt>(right==xval.length-1 or xval[right+1] - xval[i] > xval[i] - xval[left])</tt>.
* The array will be updated.
*/
private static void updateBandwidthInterval(double[] xval, int i, int[] bandwidthInterval)
{
int left = bandwidthInterval[0];
int right = bandwidthInterval[1];
// The edges should be adjusted if the previous point to the
// left is closer to x than the current point to the right or
// if the next point to the right is closer
// to x than the leftmost point of the current interval
if (left != 0 &&
xval[i] - xval[left - 1] < xval[right] - xval[i])
{
bandwidthInterval[0]++;
bandwidthInterval[1]++;
}
else if (right < xval.Length - 1 &&
xval[right + 1] - xval[i] < xval[i] - xval[left])
{
bandwidthInterval[0]++;
bandwidthInterval[1]++;
}
}
Hope someone after 5 years find this useful. This is the original code posted by Tutcugil but with the missing methods and updated.
using System;
using System.Linq;
namespace StockCorrelation
{
public class LoessInterpolator
{
public static double DEFAULT_BANDWIDTH = 0.3;
public static int DEFAULT_ROBUSTNESS_ITERS = 2;
/**
* The bandwidth parameter: when computing the loess fit at
* a particular point, this fraction of source points closest
* to the current point is taken into account for computing
* a least-squares regression.
*
* A sensible value is usually 0.25 to 0.5.
*/
private double bandwidth;
/**
* The number of robustness iterations parameter: this many
* robustness iterations are done.
*
* A sensible value is usually 0 (just the initial fit without any
* robustness iterations) to 4.
*/
private int robustnessIters;
public LoessInterpolator()
{
this.bandwidth = DEFAULT_BANDWIDTH;
this.robustnessIters = DEFAULT_ROBUSTNESS_ITERS;
}
public LoessInterpolator(double bandwidth, int robustnessIters)
{
if (bandwidth < 0 || bandwidth > 1)
{
throw new ApplicationException(string.Format("bandwidth must be in the interval [0,1], but got {0}", bandwidth));
}
this.bandwidth = bandwidth;
if (robustnessIters < 0)
{
throw new ApplicationException(string.Format("the number of robustness iterations must be non-negative, but got {0}", robustnessIters));
}
this.robustnessIters = robustnessIters;
}
/**
* Compute a loess fit on the data at the original abscissae.
*
* #param xval the arguments for the interpolation points
* #param yval the values for the interpolation points
* #return values of the loess fit at corresponding original abscissae
* #throws MathException if some of the following conditions are false:
* <ul>
* <li> Arguments and values are of the same size that is greater than zero</li>
* <li> The arguments are in a strictly increasing order</li>
* <li> All arguments and values are finite real numbers</li>
* </ul>
*/
public double[] smooth(double[] xval, double[] yval, double[] weights)
{
if (xval.Length != yval.Length)
{
throw new ApplicationException(string.Format("Loess expects the abscissa and ordinate arrays to be of the same size, but got {0} abscisssae and {1} ordinatae", xval.Length, yval.Length));
}
int n = xval.Length;
if (n == 0)
{
throw new ApplicationException("Loess expects at least 1 point");
}
checkAllFiniteReal(xval, true);
checkAllFiniteReal(yval, false);
checkStrictlyIncreasing(xval);
if (n == 1)
{
return new double[] { yval[0] };
}
if (n == 2)
{
return new double[] { yval[0], yval[1] };
}
int bandwidthInPoints = (int)(bandwidth * n);
if (bandwidthInPoints < 2)
{
throw new ApplicationException(string.Format("the bandwidth must be large enough to accomodate at least 2 points. There are {0} " +
" data points, and bandwidth must be at least {1} but it is only {2}",
n, 2.0 / n, bandwidth
));
}
double[] res = new double[n];
double[] residuals = new double[n];
double[] sortedResiduals = new double[n];
double[] robustnessWeights = new double[n];
// Do an initial fit and 'robustnessIters' robustness iterations.
// This is equivalent to doing 'robustnessIters+1' robustness iterations
// starting with all robustness weights set to 1.
for (int i = 0; i < robustnessWeights.Length; i++) robustnessWeights[i] = 1;
for (int iter = 0; iter <= robustnessIters; ++iter)
{
int[] bandwidthInterval = { 0, bandwidthInPoints - 1 };
// At each x, compute a local weighted linear regression
for (int i = 0; i < n; ++i)
{
double x = xval[i];
// Find out the interval of source points on which
// a regression is to be made.
if (i > 0)
{
updateBandwidthInterval(xval, weights, i, bandwidthInterval);
}
int ileft = bandwidthInterval[0];
int iright = bandwidthInterval[1];
// Compute the point of the bandwidth interval that is
// farthest from x
int edge;
if (xval[i] - xval[ileft] > xval[iright] - xval[i])
{
edge = ileft;
}
else
{
edge = iright;
}
// Compute a least-squares linear fit weighted by
// the product of robustness weights and the tricube
// weight function.
// See http://en.wikipedia.org/wiki/Linear_regression
// (section "Univariate linear case")
// and http://en.wikipedia.org/wiki/Weighted_least_squares
// (section "Weighted least squares")
double sumWeights = 0;
double sumX = 0, sumXSquared = 0, sumY = 0, sumXY = 0;
double denom = Math.Abs(1.0 / (xval[edge] - x));
for (int k = ileft; k <= iright; ++k)
{
double xk = xval[k];
double yk = yval[k];
double dist;
if (k < i)
{
dist = (x - xk);
}
else
{
dist = (xk - x);
}
double w = tricube(dist * denom) * robustnessWeights[k];
double xkw = xk * w;
sumWeights += w;
sumX += xkw;
sumXSquared += xk * xkw;
sumY += yk * w;
sumXY += yk * xkw;
}
double meanX = sumX / sumWeights;
double meanY = sumY / sumWeights;
double meanXY = sumXY / sumWeights;
double meanXSquared = sumXSquared / sumWeights;
double beta;
if (meanXSquared == meanX * meanX)
{
beta = 0;
}
else
{
beta = (meanXY - meanX * meanY) / (meanXSquared - meanX * meanX);
}
double alpha = meanY - beta * meanX;
res[i] = beta * x + alpha;
residuals[i] = Math.Abs(yval[i] - res[i]);
}
// No need to recompute the robustness weights at the last
// iteration, they won't be needed anymore
if (iter == robustnessIters)
{
break;
}
// Recompute the robustness weights.
// Find the median residual.
// An arraycopy and a sort are completely tractable here,
// because the preceding loop is a lot more expensive
System.Array.Copy(residuals, sortedResiduals, n);
//System.arraycopy(residuals, 0, sortedResiduals, 0, n);
Array.Sort<double>(sortedResiduals);
double medianResidual = sortedResiduals[n / 2];
if (medianResidual == 0)
{
break;
}
for (int i = 0; i < n; ++i)
{
double arg = residuals[i] / (6 * medianResidual);
robustnessWeights[i] = (arg >= 1) ? 0 : Math.Pow(1 - arg * arg, 2);
}
}
return res;
}
public double[] smooth(double[] xval, double[] yval)
{
if (xval.Length != yval.Length)
{
throw new Exception($"xval and yval len are different");
}
double[] unitWeights = Enumerable.Repeat(1.0, xval.Length).ToArray();
return smooth(xval, yval, unitWeights);
}
/**
* Given an index interval into xval that embraces a certain number of
* points closest to xval[i-1], update the interval so that it embraces
* the same number of points closest to xval[i]
*
* #param xval arguments array
* #param i the index around which the new interval should be computed
* #param bandwidthInterval a two-element array {left, right} such that: <p/>
* <tt>(left==0 or xval[i] - xval[left-1] > xval[right] - xval[i])</tt>
* <p/> and also <p/>
* <tt>(right==xval.length-1 or xval[right+1] - xval[i] > xval[i] - xval[left])</tt>.
* The array will be updated.
*/
private static void updateBandwidthInterval(double[] xval, double[] weights,
int i,
int[] bandwidthInterval)
{
int left = bandwidthInterval[0];
int right = bandwidthInterval[1];
// The right edge should be adjusted if the next point to the right
// is closer to xval[i] than the leftmost point of the current interval
int nextRight = nextNonzero(weights, right);
if (nextRight < xval.Length && xval[nextRight] - xval[i] < xval[i] - xval[left])
{
int nextLeft = nextNonzero(weights, bandwidthInterval[0]);
bandwidthInterval[0] = nextLeft;
bandwidthInterval[1] = nextRight;
}
}
private static int nextNonzero(double[] weights, int i)
{
int j = i + 1;
while (j < weights.Length && weights[j] == 0)
{
++j;
}
return j;
}
/**
* Compute the
* tricube
* weight function
*
* #param x the argument
* #return (1-|x|^3)^3
*/
private static double tricube(double x)
{
double tmp = Math.Abs(x);
tmp = 1 - tmp * tmp * tmp;
return tmp * tmp * tmp;
}
/**
* Check that all elements of an array are finite real numbers.
*
* #param values the values array
* #param isAbscissae if true, elements are abscissae otherwise they are ordinatae
* #throws MathException if one of the values is not
* a finite real number
*/
private static void checkAllFiniteReal(double[] values, bool isAbscissae)
{
for (int i = 0; i < values.Length; i++)
{
double x = values[i];
if (Double.IsInfinity(x) || Double.IsNaN(x))
{
string pattern = isAbscissae ?
"all abscissae must be finite real numbers, but {0}-th is {1}" :
"all ordinatae must be finite real numbers, but {0}-th is {1}";
throw new ApplicationException(string.Format(pattern, i, x));
}
}
}
/**
* Check that elements of the abscissae array are in a strictly
* increasing order.
*
* #param xval the abscissae array
* #throws MathException if the abscissae array
* is not in a strictly increasing order
*/
private static void checkStrictlyIncreasing(double[] xval)
{
for (int i = 0; i < xval.Length; ++i)
{
if (i >= 1 && xval[i - 1] >= xval[i])
{
throw new ApplicationException(string.Format(
"the abscissae array must be sorted in a strictly " +
"increasing order, but the {0}-th element is {1} " +
"whereas {2}-th is {3}",
i - 1, xval[i - 1], i, xval[i]));
}
}
}
}
}
The source data :
static double[] felix = new double[] { 0.003027523, 0.002012256, -0.001369238, -0.001737660, -0.001647287,
0.000275154, 0.002017238, 0.001372621, 0.000274148, -0.000913576, 0.001920263, 0.001186456, -0.000364631,
0.000638337, 0.000182266, -0.001275626, -0.000821093, 0.001186998, -0.000455996, -0.000547445, -0.000182582,
-0.000547845, 0.001279006, 0.000456204, 0.000000000, -0.001550388, 0.001552795, 0.000729594, -0.000455664,
-0.002188184, 0.000639620, 0.000091316, 0.001552228, -0.001002826, 0.000182515, -0.000091241, -0.000821243,
-0.002009132, 0.000000000, 0.000823572, 0.001920088, -0.001368863, 0.000000000, 0.002101800, 0.001094291,
0.001639643, 0.002637323, 0.000000000, -0.000172336, -0.000462665, -0.000136141 };
The variance function:
public static double Variance(double[] x)
{
if (x.Length == 0)
return 0;
double sumX = 0;
double sumXsquared = 0;
double varianceX = 0;
int dataLength = x.Length;
for (int i = 0; i < dataLength; i++)
{
sumX += x[i];
sumXsquared += x[i] * x[i];
}
varianceX = (sumXsquared / dataLength) - ((sumX / dataLength) * (sumX / dataLength));
return varianceX;
}
Excel and some online calculator says the variance is 1.56562E-06
While my function gives me 1.53492394804015E-06. I begin to doubt if the C# has accuracy problem or what. Is there anyone have this kind of problem before?
What you are seeing is the difference between sample variance and population variance and nothing to do with floating point precision or the accuracy of C#'s floating point implementation.
You are calculating population variance. Excel and that web site are calculating sample variance.
Var and VarP are distinct calculations and you do need to be careful about which one you are using. (unfortunately people often refer to them as if they are interchangeable when they are not. The same is true for standard deviation)
Sample variance for your data is 1.56562E-06, population variance is 1.53492394804015E-06.
From some code posted on codeproject awhile back:
Variance in a sample
public static double Variance(this IEnumerable<double> source)
{
double avg = source.Average();
double d = source.Aggregate(0.0, (total, next) => total += Math.Pow(next - avg, 2));
return d / (source.Count() - 1);
}
Variance in a population
public static double VarianceP(this IEnumerable<double> source)
{
double avg = source.Average();
double d = source.Aggregate(0.0, (total, next) => total += Math.Pow(next - avg, 2));
return d / source.Count();
}
Here's an alternate implementation, that is sometimes better-behaved, numerically:
mean = Average(data);
double sum2 = 0.0, sumc = 0.0;
for (int i = 0; i < data.Count; i++)
{
double dev = data[i] - mean;
sum2 += dev * dev;
sumc += dev;
}
return (sum2 - sumc * sumc / data.Count) / data.Count;
I'm running some Monte Carlo simulations and making extensive use of the Excel function NORM.INV using Office Interrop. This functions takes three arguments (probability, average, standard deviation) and returns the inverse of the cumulative distribution.
I'd like to move my code into a web app, but that will require installing Excel on the server. Does anybody know of a C# statistics library that has an equivalent function to NORM.INV?
Meta.Numerics has exactly what you are looking for. Here is the code to do it using that library:
Distribution n = new NormalDistribution(mean, standardDeviation);
double x = n.InverseLeftProbability(probability);
If you are doing this in order to generate normal deviates, the GetRandomValue function is even faster.
I was also needing a C# implementation of NORMINV, the closest thing I found was a C++ implementation http://www.wilmott.com/messageview.cfm?catid=10&threadid=38771, so I made a quick and dirty translation to C#, the details here http://weblogs.asp.net/esanchez/archive/2010/07/29/a-quick-and-dirty-implementation-of-excel-norminv-function-in-c.aspx. I have made only a few basic tests so be careful if you decide to use it, anyway, hope it helps!
https://numerics.mathdotnet.com/ has a pretty neat looking library that deals with stats (so I assume the CDF), I've not used it so I can't say for definite that it's what you want, but it seems like it should be.
The inverse normal CDF, including coefficients, is described here. And the absolute value of the relative error is less than 1.15 × 10−9
public static class NormalDistributionConfidenceCalculator
{
/// <summary>
///
/// </summary>
public static double InverseNormalDistribution(double probability, double min, double max)
{
double x = 0;
double a = 0;
double b = 1;
double precision = Math.Pow(10, -3);
while ((b - a) > precision)
{
x = (a + b) / 2;
if (NormInv(x) > probability)
{
b = x;
}
else
{
a = x;
}
}
if ((max > 0) && (min > 0))
{
x = x * (max - min) + min;
}
return x;
}
/// <summary>
/// Returns the cumulative density function evaluated at A given value.
/// </summary>
/// <param name="x">A position on the x-axis.</param>
/// <param name="mean"></param>
/// <param name="sigma"></param>
/// <returns>The cumulative density function evaluated at <C>x</C>.</returns>
/// <remarks>The value of the cumulative density function at A point <C>x</C> is
/// probability that the value of A random variable having this normal density is
/// less than or equal to <C>x</C>.
/// </remarks>
public static double NormalDistribution(double x, double mean, double sigma)
{
// This algorithm is ported from dcdflib:
// Cody, W.D. (1993). "ALGORITHM 715: SPECFUN - A Portabel FORTRAN
// Package of Special Function Routines and Test Drivers"
// acm Transactions on Mathematical Software. 19, 22-32.
int i;
double del, xden, xnum, xsq;
double result, ccum;
double arg = (x - mean) / sigma;
const double sixten = 1.60e0;
const double sqrpi = 3.9894228040143267794e-1;
const double thrsh = 0.66291e0;
const double root32 = 5.656854248e0;
const double zero = 0.0e0;
const double min = Double.Epsilon;
double z = arg;
double y = Math.Abs(z);
const double half = 0.5e0;
const double one = 1.0e0;
double[] a =
{
2.2352520354606839287e00, 1.6102823106855587881e02, 1.0676894854603709582e03,
1.8154981253343561249e04, 6.5682337918207449113e-2
};
double[] b =
{
4.7202581904688241870e01, 9.7609855173777669322e02, 1.0260932208618978205e04,
4.5507789335026729956e04
};
double[] c =
{
3.9894151208813466764e-1, 8.8831497943883759412e00, 9.3506656132177855979e01,
5.9727027639480026226e02, 2.4945375852903726711e03, 6.8481904505362823326e03,
1.1602651437647350124e04, 9.8427148383839780218e03, 1.0765576773720192317e-8
};
double[] d =
{
2.2266688044328115691e01, 2.3538790178262499861e02, 1.5193775994075548050e03,
6.4855582982667607550e03, 1.8615571640885098091e04, 3.4900952721145977266e04,
3.8912003286093271411e04, 1.9685429676859990727e04
};
double[] p =
{
2.1589853405795699e-1, 1.274011611602473639e-1, 2.2235277870649807e-2,
1.421619193227893466e-3, 2.9112874951168792e-5, 2.307344176494017303e-2
};
double[] q =
{
1.28426009614491121e00, 4.68238212480865118e-1, 6.59881378689285515e-2,
3.78239633202758244e-3, 7.29751555083966205e-5
};
if (y <= thrsh)
{
//
// Evaluate anorm for |X| <= 0.66291
//
xsq = zero;
if (y > double.Epsilon) xsq = z * z;
xnum = a[4] * xsq;
xden = xsq;
for (i = 0; i < 3; i++)
{
xnum = (xnum + a[i]) * xsq;
xden = (xden + b[i]) * xsq;
}
result = z * (xnum + a[3]) / (xden + b[3]);
double temp = result;
result = half + temp;
}
//
// Evaluate anorm for 0.66291 <= |X| <= sqrt(32)
//
else if (y <= root32)
{
xnum = c[8] * y;
xden = y;
for (i = 0; i < 7; i++)
{
xnum = (xnum + c[i]) * y;
xden = (xden + d[i]) * y;
}
result = (xnum + c[7]) / (xden + d[7]);
xsq = Math.Floor(y * sixten) / sixten;
del = (y - xsq) * (y + xsq);
result = Math.Exp(-(xsq * xsq * half)) * Math.Exp(-(del * half)) * result;
ccum = one - result;
if (z > zero)
{
result = ccum;
}
}
//
// Evaluate anorm for |X| > sqrt(32)
//
else
{
xsq = one / (z * z);
xnum = p[5] * xsq;
xden = xsq;
for (i = 0; i < 4; i++)
{
xnum = (xnum + p[i]) * xsq;
xden = (xden + q[i]) * xsq;
}
result = xsq * (xnum + p[4]) / (xden + q[4]);
result = (sqrpi - result) / y;
xsq = Math.Floor(z * sixten) / sixten;
del = (z - xsq) * (z + xsq);
result = Math.Exp(-(xsq * xsq * half)) * Math.Exp(-(del * half)) * result;
ccum = one - result;
if (z > zero)
{
result = ccum;
}
}
if (result < min)
result = 0.0e0;
return result;
}
/// <summary>
/// Given a probability, a mean, and a standard deviation, an x value can be calculated.
/// </summary>
/// <returns></returns>
public static double NormInv(double probability)
{
const double a1 = -39.6968302866538;
const double a2 = 220.946098424521;
const double a3 = -275.928510446969;
const double a4 = 138.357751867269;
const double a5 = -30.6647980661472;
const double a6 = 2.50662827745924;
const double b1 = -54.4760987982241;
const double b2 = 161.585836858041;
const double b3 = -155.698979859887;
const double b4 = 66.8013118877197;
const double b5 = -13.2806815528857;
const double c1 = -7.78489400243029E-03;
const double c2 = -0.322396458041136;
const double c3 = -2.40075827716184;
const double c4 = -2.54973253934373;
const double c5 = 4.37466414146497;
const double c6 = 2.93816398269878;
const double d1 = 7.78469570904146E-03;
const double d2 = 0.32246712907004;
const double d3 = 2.445134137143;
const double d4 = 3.75440866190742;
//Define break-points
// using Epsilon is wrong; see link above for reference to 0.02425 value
//const double pLow = double.Epsilon;
const double pLow = 0.02425;
const double pHigh = 1 - pLow;
//Define work variables
double q;
double result = 0;
// if argument out of bounds.
// set it to a value within desired precision.
if (probability <= 0)
probability = pLow;
if (probability >= 1)
probability = pHigh;
if (probability < pLow)
{
//Rational approximation for lower region
q = Math.Sqrt(-2 * Math.Log(probability));
result = (((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) / ((((d1 * q + d2) * q + d3) * q + d4) * q + 1);
}
else if (probability <= pHigh)
{
//Rational approximation for lower region
q = probability - 0.5;
double r = q * q;
result = (((((a1 * r + a2) * r + a3) * r + a4) * r + a5) * r + a6) * q /
(((((b1 * r + b2) * r + b3) * r + b4) * r + b5) * r + 1);
}
else if (probability < 1)
{
//Rational approximation for upper region
q = Math.Sqrt(-2 * Math.Log(1 - probability));
result = -(((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) / ((((d1 * q + d2) * q + d3) * q + d4) * q + 1);
}
return result;
}
/// <summary>
///
/// </summary>
/// <param name="probability"></param>
/// <param name="mean"></param>
/// <param name="sigma"></param>
/// <returns></returns>
public static double NormInv(double probability, double mean, double sigma)
{
double x = NormInv(probability);
return sigma * x + mean;
}
}
I do not know of a library, but found this link - http://home.online.no/~pjacklam/notes/invnorm/ - describing an algoritm. It has implementations in a number of languages, but not C#. You could use the VB.NET version, or port it yourself.
Maybe you can try this component,http://www.smartxls.com,it has an Excel compatible runtime calculation engine and it does not need Excel installed.
add a chart control
double result = Chart1.DataManipulator.Statistics.InverseNormalDistribution(probability);
probability eg : 0.9, 0.4