2011-09-01 37 views
3

我有兩個函數用於包含(-180,180]和(-π,π]之間的角度,目的是給定從-inf到+ inf的任何角度,它將保留。指定的時間間隔相等的角度。例如1550°的角度是110°Math.Round()的不一致性()

public double WrapBetween180(double angle) 
{ 
    return angle - 360d * Math.Round(angle/360d, MidpointRounding.AwayFromZero); 
} 
public double WrapBetweenPI(double angle) 
{ 
    const double twopi = 2d * Math.PI; 
    return angle - twopi * Math.Round(angle/twopi, MidpointRounding.AwayFromZero); 
} 

這將產生以下結果

WrapBetween180(-180) = -180 
WrapBetween180(180) = 180 

WrapBetweenPI(-Math.PI) = Math.PI 
WrapBetweenPI(Math.PI) = -Math.PI 

其中沒有一個是我要的是什麼,我想是:

WrapBetween180(-180) = 180 
WrapBetween180(180) = 180 

WrapBetweenPI(-Math.PI) = Math.PI 
WrapBetweenPI(Math.PI) = Math.PI 

我嘗試了四捨五入的方法,但仍然無法獲得理想的效果。問題是顯而易見的,因爲有時候我處理的角度只能近似於-π或π,而我的結果會導致不連續性。

關於如何最佳地實現角度環繞功能以及非包含下限和包含上限的任何建議?

+1

每雙應該是π是「只有大約接近π」 :-) –

+1

這些是什麼方法,怎麼辦呢?我看不到它的目的... –

+1

你是說你真的想要Math.Abs​​(value1)的回報; 其中value1是您當前功能的結果? –

回答

2

對於度的角度,如果x是-180到180之間,然後是180 - x 360介於0和你想要的是相當於問這個180 - x介於0(含),和360(不包括)。所以,一旦180 - x達到360,我們想要添加360到角度。這給了我們:在弧度的角度

return angle + 360d * Math.Floor((180d - angle)/360d); 

同一件事:

return angle + twopi * Math.Floor((Math.PI - angle)/twopi); 
0

它不解決四捨五入問題,但這裏是我怎麼會到你想要做什麼:

private static double ConvertAngle(double angle) 
{ 
    bool isNegative = angle < 0; 
    if (isNegative) 
     angle *= -1; 

    angle = angle % 360; 
    if (isNegative) 
     angle = -1 * angle + 360; 

    if (angle > 180) 
     angle = (angle - 360); 

    return angle; 
} 

注意:這種方式假設你要「後面」是180度,而不是-180度。

0

這不是模數操作的情況嗎?

private double Wrap180(double value) 
{ 
    // exact rounding of corner values 
    if (value == 180) return 180.0; 
    if (value == -180) return 180.0; 

    // "shift" by 180 and use module, then shift back. 
    double wrapped = ((Math.Abs(value) + 180.0) % 360.0) - 180.0; 

    // handle negative values correctly 
    if (value < 0) return -wrapped; 
    return wrapped; 
} 

,傳遞這個測試

Assert.AreEqual(170.0, wrap(-190.0)); 
    Assert.AreEqual(180.0, wrap(-180.0)); 
    Assert.AreEqual(-170.0, wrap(-170.0)); 
    Assert.AreEqual(0.0, wrap(0.0)); 
    Assert.AreEqual(10.0, wrap(10.0)); 
    Assert.AreEqual(170.0, wrap(170.0)); 
    Assert.AreEqual(180.0, wrap(180.0)); 
    Assert.AreEqual(-170.0, wrap(190.0)); 
+0

我喜歡使用模數的方法,但我想知道它是如何執行的,相對於大數字的'Math.Floor()'函數。老實說,我不知道哪個更強大的方法。 – ja72