我看到我可以用(比如)
声明一个函数public double Function(double parameter)
但如果我想采用该功能的衍生物呢?
答案 0 :(得分:33)
您无法使用计算机程序计算函数的精确导数(除非您正在进行符号数学......但这是另一种更复杂的主题)。
计算函数的数值导数有几种方法。最简单的是中心三点法:
[f(x+h) - f(x-h)] / 2h
另一种方法是中心五点法:
[f(x-2h) - 8f(x-h) + 8f(x+h) - f(x+2h)] / 12h
另一个主题是如何使用C#实现这一点。首先,您需要一个代表一个函数的委托,该函数将实数的一个子集映射到另一个实数的子集:
delegate double RealFunction(double arg);
然后,您需要一个评估衍生的路由:
public double h = 10e-6; // I'm not sure if this is valid C#, I'm used to C++
static double Derivative(RealFunction f, double arg)
{
double h2 = h*2;
return (f(x-h2) - 8*f(x-h) + 8*f(x+h) - f(x+h2)) / (h2*6);
}
如果需要面向对象的实现,则应创建以下类:
interface IFunction
{
// Since operator () can't be overloaded, we'll use this trick.
double this[double arg] { get; }
}
class Function : IFunction
{
RealFunction func;
public Function(RealFunction func)
{ this.func = func; }
public double this[double arg]
{ get { return func(arg); } }
}
class Derivative : IFunction
{
IFunction func;
public static double h = 10e-6;
public Derivative(IFunction func)
{ this.func = func; }
public double this[double arg]
{
get
{
double h2 = h*2;
return (
func[arg - h2] - func[arg + h2] +
( func[arg + h] - func[arg - h] ) * 8
) / (h2 * 6);
}
}
}
答案 1 :(得分:7)
如果您正在考虑对公式进行符号处理,那么您最好使用Maple或Mathematica等语言进行推导。它们是为符号计算而设计的。
编辑:如果Maple和Mathematica对你来说太昂贵,那么还有其他选择。维基百科有一个相当完整的计算机代数包列表。 http://en.wikipedia.org/wiki/Comparison_of_computer_algebra_systems
答案 2 :(得分:1)
您在考虑Lambda表达式吗?
基本上你可以将一个函数传递给一个函数。
所以想一下对象的排序。 根据对象的性质,将有助于确定对象的排序方式。
但是你仍然可以创建一个通用排序函数,然后传递如何比较对象。
答案 3 :(得分:1)
另一种方法可以是利用衍生数字的众所周知的定义来利用扩展方法,并相应地计算其近似值。
正如已经提到过的,对于数字方法而言,这很容易,而不是象征性方法:
public partial static class IEnumerableExtensions
{
public static IEnumerable<Double> Derivate1<TSource>(this IEnumerable<TSource> source, Func<TSource, Double> selectorX, Func<TSource, Double> selectorY)
{
var enumerator = source.GetEnumerator();
enumerator.Reset();
enumerator.MoveNext();
var itemPrevious = enumerator.Current;
var itemNext = default(TSource);
while (enumerator.MoveNext())
{
itemNext = enumerator.Current;
var itemPreviousX = selectorX(itemPrevious);
var itemPreviousY = selectorY(itemPrevious);
var itemNextX = selectorX(itemNext);
var itemNextY = selectorY(itemNext);
var derivative = (itemNextY - itemPreviousY) / (itemNextX - itemPreviousX);
yield return derivative;
itemPrevious = itemNext;
}
}
}
或者如果你更喜欢foreach
时尚
public partial static class IEnumerableExtensions
{
public static IEnumerable<Double> Derivate2<TSource>(IEnumerable<TSource> source, Func<TSource, Double> selectorX, Func<TSource, Double> selectorY)
{
var itemPrevious = source.First();
source = source.Skip(1);
foreach (var itemNext in source)
{
var itemPreviousX = selectorX(itemPrevious);
var itemPreviousY = selectorY(itemPrevious);
var itemNextX = selectorX(itemNext);
var itemNextY = selectorY(itemNext);
var derivative = (itemNextY - itemPreviousY) / (itemNextX - itemPreviousX);
yield return derivative;
itemPrevious = itemNext;
}
}
}
您可以按以下方式重构所有内容:
public static partial class MathHelpers
{
public static Double Derivate(Double xPrevious, Double xNext, Double yPrevious, Double yNext)
{
var derivative = (yNext - yPrevious)/(xNext - xPrevious);
return derivative;
}
}
public static class IEnumerableExtensions
{
public static IEnumerable<Double> Derivate<TSource>(IEnumerable<TSource> source, Func<TSource, Double> selectorX, Func<TSource, Double> selectorY)
{
var itemPrevious = source.First();
source = source.Skip(1);
foreach (var itemNext in source)
{
var derivative = MathHelpers.Derivate(selectorX(itemPrevious), selectorX(itemNext), selectorY(itemPrevious), selectorY(itemNext));
yield return derivative;
itemPrevious = itemNext;
}
}
}
答案 4 :(得分:0)
如果您已经编写了该函数,那么它已经被派生出来了。
鉴于它是一个int函数,我假设你并不是指“派生”的微积分定义。