.NET 插值计算?

发布于 2024-10-14 04:52:14 字数 801 浏览 8 评论 0原文

我正在寻找一个灵活的解决方案(如果它需要是一个 .NET 数学库,那就这样吧)。

我有两个 DateTime 变量,即 FromTo。我还有两个数值 StartFinish

我想在相对于 FromAt TimeSpan 处获取 StartFinish 之间的值。

请参阅:

//At is the TimeSpan which should be added to From to get the location of the point to be interpolated
GetInterpolatedValue(At, From, To, Start, Finish, InterpolationMethod, Optional InterpolationVars = Nothing)

示例:

GetInterPolatedValue(TimeSpan.FromDays(1), Now(), Now.AddDays(2), 1, 3, InterpolationMethod.Linear, Nothing)

应该返回: 2

我应该如何实现这个?我只需要能够线性插值和曲线插值(指数?对不起我的非代数语言)。

(顺便说一句,我将日期时间/时间跨度四舍五入为天)

I'm looking for a slick solution (if it needs to be a .NET Math library so be it) for the following.

I two DateTime variables, say From and To. I also have two numerical values Start and Finish.

I want to get the value between Start and Finish at the At TimeSpan relative to From.

See:

//At is the TimeSpan which should be added to From to get the location of the point to be interpolated
GetInterpolatedValue(At, From, To, Start, Finish, InterpolationMethod, Optional InterpolationVars = Nothing)

Example:

GetInterPolatedValue(TimeSpan.FromDays(1), Now(), Now.AddDays(2), 1, 3, InterpolationMethod.Linear, Nothing)

Should return: 2

How should I implement this? I just need to be able to interpolate linearly and with a curve (exponential? sorry for my non-algebraic language).

(btw I'm rounding the DateTime / TimeSpan to days)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

墨离汐 2024-10-21 04:52:14

因为我已经一遍又一遍地写过类似的东西,所以我首先编写了一个包含以下函数的类:

    /// <summary>
    /// Calculate the position, of a given value, within a certain range/size
    /// depending on the minimum and maximum (scale) for the value.
    /// </summary>
    /// <param name="data">Value for which to calculate the position.</param>
    /// <param name="minimum_value">Minimum value of the scale on which the value must lie.</param>
    /// <param name="maximum_value">Maximum value of the scale on which the value must lie.</param>
    /// <param name="size_begin">The begin value of the size on which the scale must be spread.</param>
    /// <param name="size_end">The end value of the size on which the scale must be spread.</param>
    /// <returns>The respectively positions of the data value.</returns>
    static public double Position_In_Size(double data, double minimum_value, double maximum_value, double size_begin, double size_end)
    {
        return size_begin + (((size_end - size_begin) / (maximum_value - minimum_value)) * (data - minimum_value));
    }

这很快就成为一个非常大的类,以支持所有类型。 C# 不支持开箱即用的值类型泛型。

最近我发现了一个在 .NET 中实现泛型的库并提供了解决方法。

使用这个库我现在有了一个更干净的实现。使用通用间隔类,我可以将值从一个范围“映射”到另一个范围,而与类型无关。

// Result will be 0.
Interval<int> interval = new Interval<int>( 0, 10 );
double result = interval.Map<double>( 5, new Interval<double>( -100, 100 ) );

我写这个作为我正在研究的一些插值类的一部分:
http://whathecode.wordpress.com/2011/01/24/ interpolation-no-more/

源代码可以在我的FCL扩展库,在命名空间 Whathecode.System.Arithmetic.Range 中。

Because I have written something similar over and over again, I first wrote a class containing functions like:

    /// <summary>
    /// Calculate the position, of a given value, within a certain range/size
    /// depending on the minimum and maximum (scale) for the value.
    /// </summary>
    /// <param name="data">Value for which to calculate the position.</param>
    /// <param name="minimum_value">Minimum value of the scale on which the value must lie.</param>
    /// <param name="maximum_value">Maximum value of the scale on which the value must lie.</param>
    /// <param name="size_begin">The begin value of the size on which the scale must be spread.</param>
    /// <param name="size_end">The end value of the size on which the scale must be spread.</param>
    /// <returns>The respectively positions of the data value.</returns>
    static public double Position_In_Size(double data, double minimum_value, double maximum_value, double size_begin, double size_end)
    {
        return size_begin + (((size_end - size_begin) / (maximum_value - minimum_value)) * (data - minimum_value));
    }

This quickly became a really big class, in order to support all kind of types. C# doesn't support generics for value types out of the box.

Recently I found a library which implements generics in .NET with a workaround.

Using this library I now have a cleaner implementation. Using a generic interval class, I can 'map' values from one range to another, independant of type.

// Result will be 0.
Interval<int> interval = new Interval<int>( 0, 10 );
double result = interval.Map<double>( 5, new Interval<double>( -100, 100 ) );

I wrote this as part of some interpolation classes I was working on:
http://whathecode.wordpress.com/2011/01/24/interpolation-no-more/

The source code can be found in my FCL Extension library, in the namespace Whathecode.System.Arithmetic.Range.

心如荒岛 2024-10-21 04:52:14

我会使用类似(伪代码)(((At-From)/(To-From)) * (Finish-Start)) + Start 的内容。

I would use something along the lines of (in pseudocode) (((At-From)/(To-From)) * (Finish-Start)) + Start.

夏九 2024-10-21 04:52:14

我用测试代码编写了示例。它按照您的描述工作,但没有可选参数。你需要它做什么?

    private static double GetValueAt(TimeSpan at, DateTime from, DateTime to, double start, double end, Func<TimeSpan, double> function)
    {
        // fullFunction(time) = k *  function(time) + a 
        // k and a are calculated according to start and end values
        TimeSpan totalTime = to - from;
        double k = (end - start) / function(totalTime);
        double a = start - k * function(new TimeSpan(0));
        Func<TimeSpan, double> fullFunction = t => k * function(t) + a;
        return fullFunction(at);
    }

    static void Main(string[] args)
    {
        Func<TimeSpan, double> f1 = t => t.TotalDays;
        Func<TimeSpan, double> fx2 = t => t.TotalDays * 2;
        Func<TimeSpan, double> fsquare = t => Math.Pow(t.TotalDays, 2);

        var f1Value = GetValueAt(TimeSpan.FromDays(1), DateTime.Today, DateTime.Today.AddDays(4), 1, 5, f1); // 2
        var fx2Value = GetValueAt(TimeSpan.FromDays(1), DateTime.Today, DateTime.Today.AddDays(4), 1, 9, fx2); // 3
        var fsquareValue = GetValueAt(TimeSpan.FromDays(1), DateTime.Today, DateTime.Today.AddDays(2), 1, 5, fsquare); // 2
    }

I wrote the sample with the test code. It works as you described but without optional parameter. What do you need it for?

    private static double GetValueAt(TimeSpan at, DateTime from, DateTime to, double start, double end, Func<TimeSpan, double> function)
    {
        // fullFunction(time) = k *  function(time) + a 
        // k and a are calculated according to start and end values
        TimeSpan totalTime = to - from;
        double k = (end - start) / function(totalTime);
        double a = start - k * function(new TimeSpan(0));
        Func<TimeSpan, double> fullFunction = t => k * function(t) + a;
        return fullFunction(at);
    }

    static void Main(string[] args)
    {
        Func<TimeSpan, double> f1 = t => t.TotalDays;
        Func<TimeSpan, double> fx2 = t => t.TotalDays * 2;
        Func<TimeSpan, double> fsquare = t => Math.Pow(t.TotalDays, 2);

        var f1Value = GetValueAt(TimeSpan.FromDays(1), DateTime.Today, DateTime.Today.AddDays(4), 1, 5, f1); // 2
        var fx2Value = GetValueAt(TimeSpan.FromDays(1), DateTime.Today, DateTime.Today.AddDays(4), 1, 9, fx2); // 3
        var fsquareValue = GetValueAt(TimeSpan.FromDays(1), DateTime.Today, DateTime.Today.AddDays(2), 1, 5, fsquare); // 2
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文