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
您的主要问题是热算法与时间有关。你计算的热点分数在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
成为常量。