2

我正在处理物理实体,例如时间、速度和距离,并执行简单的数学运算,例如距离 = 时间 * 速度等。速度和距离是四舍五入到第 8 位的双精度值,对于时间值是​​ .NET TimeSpan用来。由于 TimeSpan 舍入到最接近的毫秒,我得到舍入错误,所以我需要编写自定义舍入方法,将所有计算舍入到最接近的毫秒。例如(为简单起见,省略了舍入到第 8 位):

  static void Main(string[] args) {
     var dist = 1.123451;
     var speed = 1.123452;

     var timeA = TimeSpan.FromHours(dist / speed);
     var timeB = timeA + TimeSpan.FromMilliseconds(1);

     var distA = _round(timeA.TotalHours * speed);
     var distB = _round(timeB.TotalHours * speed);

     var timeA1 = TimeSpan.FromHours(distA / speed);
     var timeB1 = TimeSpan.FromHours(distB / speed);

     // a correct implementation should give both the following vars true
     var isDistributive = distA == dist;
     var isPrecise = (timeB1 - timeA1) == TimeSpan.FromMilliseconds(1);
  }

  public static double _round(double d) {
     // Q: what should be here?
  }
  • 使用 Math.Round(d, 6) 是分布式的,但会丢失精度(精确到 ~4 毫秒)
  • 使用 Math.Round(d, 7) 精确到单个毫秒,但不是分布的(上面的 distA 将为 1.1234511 != 1.123451)
  • 使用以下(舍入到最接近的毫秒)似乎是正确的,但舍入代码本身会引入其自身的双精度错误:

      public static double _round(double d) {
        var pre = 3600000.0;
        return Math.Round(d * pre) / pre;
      }
    

谢谢,鲍里斯。

4

2 回答 2

2

Jon Skeet对 .Net 时间计算同样不满意,并且正在从事一个名为noda-time的项目,我相信这可能会解决这个问题。我不知道该项目是否足以对您有用,但值得检查。

编辑:无耻地调用 JS 的名称,希望让人们使用和改进库,而不是(不必要地)重新发明轮子。

于 2010-07-26T23:19:46.753 回答
0

尝试使用十进制而不是双精度类型。它们更精确(28 位精度)并且应该满足您的需要,而无需实现自定义回合功能。

于 2010-07-26T17:56:54.153 回答