2010-07-26 89 views
2

我正在處理的物理實體,如時間,速度和距離,並執行簡單的數學,如距離=時間*速度等。速度和距離是四捨五入到第8位的雙倍值,對於Time值,使用.NET TimeSpan。由於TimeSpan四捨五入到最接近的毫秒,所以我得到了四捨五入的錯誤,所以我需要編寫自定義四捨五入方法,將所有計算四捨五入到最接近的毫秒。例如(四捨五入至第八位爲了簡化省略):TimeSpan和雙舍入錯誤

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毫秒)
  • 使用數學。圓(d,7)精確到一毫秒,但不是分配(distA以上將是1.1234511!= 1.123451)
  • 使用以下(舍入到最近的msec)似乎是正確的,但舍入代碼本身引入了自己的雙精度誤差:

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

謝謝, 鮑里斯。

回答

2

Jon Skeet同樣不滿意.Net時間計算,並且在一個名爲noda-time的項目上工作,我相信這可以解決這個問題。我不知道這個項目是否足夠適合你,但是值得檢查一下。

編輯:無恥地援引JS的名字,希望讓人們使用和改進圖書館,而不是(不必要地)重新發明輪子。

0

嘗試使用十進制而不是雙重類型。它們更精確(28位精度),並且不需要實現自定義輪功能就可以滿足您的需求。

+0

我的問題是不失雙精度,我的問題是在TimeSpan.FromHours失去精度 – Borka 2010-07-26 18:02:06