Python 到 C# 移植后计算错误

本文关键字:计算 错误 Python | 更新日期: 2024-10-30 16:29:32

我正在研究基于Reddit模型的帖子系统的时间衰减算法:http://amix.dk/blog/post/19588

我的工作端口在这里:

public class Calculation
{
    protected DateTime Epoch = new DateTime(1970, 1, 1);
    protected long EpochSeconds(DateTime dt)
    {
        var ts = dt.Subtract(Convert.ToDateTime("1/1/1970 8:00:00 AM"));
        return ((((((ts.Days * 24) + ts.Hours) * 60) + ts.Minutes) * 60) + ts.Seconds);
    }
    protected int Score(int upVotes, int downVotes)
    {
        return upVotes - downVotes;
    }
    public double HotScore(int upVotes, int downVotes, DateTime date)
    {
        var s = Score(upVotes, downVotes);
        var order = Math.Log(Math.Max(Math.Abs(s), 1), 10);
        var sign = Math.Sign(s);
        var seconds = EpochSeconds(date) - 1134028003;
        return Math.Round(order + sign * ((double)seconds / 45000), 7);
    }
}

根据提供的链接的模型输出,我应该看到 0-13 小时逐渐衰减,之后急剧衰减。

我看到的是非常均匀的衰减,得分远高于原始代码的输出(原始代码:3480-3471)。

以下是我的测试方式:

        Calculation c = new Calculation();
        double now = c.HotScore(100, 2, DateTime.Now);
        double fivehoursago = c.HotScore(100, 2, DateTime.Now.AddHours(-5));
        double tenhoursago = c.HotScore(100, 2, DateTime.Now.AddHours(-10));
        double elevenhoursago = c.HotScore(100, 2, DateTime.Now.AddHours(-11));
        double twelvehoursago = c.HotScore(100, 2, DateTime.Now.AddHours(-12));
        double thirteenhoursago = c.HotScore(100, 2, DateTime.Now.AddHours(-13));
        double fiftyhoursago = c.HotScore(100, 2, DateTime.Now.AddHours(-50));
        double onehundredhoursago = c.HotScore(100, 2, DateTime.Now.AddHours(-100));
        Console.WriteLine(now.ToString());
        Console.WriteLine(fivehoursago.ToString());
        Console.WriteLine(tenhoursago.ToString());
        Console.WriteLine(elevenhoursago.ToString());
        Console.WriteLine(twelvehoursago.ToString());
        Console.WriteLine(thirteenhoursago.ToString());
        Console.WriteLine(fiftyhoursago.ToString());
        Console.WriteLine(onehundredhoursago.ToString());
        Console.ReadLine();

输出值:

now:               4675.2993816
five hours:        4674.8993816
ten hours:         4674.4993816
eleven hours:      4674.4193816
twelve hours:      4674.3393816
thirteen hours:    4674.2593816
fifty hours:       4671.2993816
one-hundred hours: 4667.2993816

显然,它的工作正常,但有些东西不对劲。这可能与缺乏真正的 *nix Epoch支持或缺乏类似的微秒计算有关,但有些事情不太对劲。

可能的参考资源:http://blogs.msdn.com/b/brada/archive/2004/03/20/93332.aspxhttp://codeclimber.net.nz/archive/2007/07/10/convert-a-unix-timestamp-to-a-.net-datetime.aspx

Python 到 C# 移植后计算错误

您的主要问题是热算法与时间有关。你计算的热点分数在DateTime.Now,而文章写在23。2010 年 11 月(查看文章底部)。

经过一些试验和错误,数据似乎是在大约 2010-11-23 07:35 计算得出的。尝试使用该值而不是DateTime.Now ,您应该得到与所示图表中的数据大致相同的结果。

请注意,您可以对代码进行以下改进:

public class Calculation
{
    private static readonly DateTime Epoch = new DateTime(1970, 1, 1);
    private double EpochSeconds(DateTime dt)
    {
        return (dt - Epoch).TotalSeconds;
    }
    private int Score(int upVotes, int downVotes)
    {
        return upVotes - downVotes;
    }
    public double HotScore(int upVotes, int downVotes, DateTime date)
    {
        int s = Score(upVotes, downVotes);
        double order = Math.Log(Math.Max(Math.Abs(s), 1), 10);
        int sign = Math.Sign(s);
        double seconds = EpochSeconds(date) - 1134028003;
        return Math.Round(order + sign * seconds / 45000, 7);
    }
}

我的结果:

3479.0956039
3478.6956039
3478.2956039
3478.2156039
3478.1356039
3478.0556039
3475.0956039
3471.0956039

变化:

  • 使用了声明的纪元而不是 1970-01-01 08:00:00 的转换(我认为 08:00 是一个错误)。
  • 你可以用a - b减去两个日期;这与a.Subtract(b)相同,但更简洁,它反映了原始的Python代码。
  • 时间跨度确实为您提供微秒精度(刻度是最小的单位,等于 100 纳秒)。
  • 此外,TotalSeconds 为您提供时间跨度内的总秒数;无需重新计算。分数部分甚至为您提供微秒精度。
  • 通过从纪元秒返回双精度,您可以保持此精度。
  • 使数据类型显式而不是var以清楚地指示哪个变量是什么(它们与方法签名匹配,因此没有隐式向上转换)。
  • 将不需要的protected更改为private,并使Epoch成为常量。