我有一个代表形状的类。 Shape类有一个名为Angle的属性。我希望此属性的setter自动将值包装到[0,359]范围内。
不幸的是,简单的_Angle = value % 360;
仅适用于正数。在C#中,-40 % 360 == -40
。 Google calc会做the way I want it。该值应为320。
C#中最优雅的解决方案是什么?
这是我到目前为止最好的方式:
public double Angle {
get { return _Angle; }
set {
if ( value >= 0 ) {
_Angle = value % 360;
}
else {
_Angle = value - (360 * ((int)(value / 360) - 1));
}
}
}
修改
谢谢你们,我现在有:
public double Angle {
get { return _Angle; }
set {
_Angle = (value % 360) + ((value < 0) ? 360 : 0);
}
}
..哪个好多了:)
答案 0 :(得分:9)
虽然这是针对Java的,但Java对模数也有相同的行为。 (即-40 % 360 == -40
)。
以下代码应该从[0。 360),无论给定的角度,正面还是负面。
public class Mod
{
public static int mod(int a, int b)
{
if (a < 0)
return b + (a % b);
else
return a % b;
}
public static void main(String[] args)
{
System.out.println(mod(40, 360)); // 40
System.out.println(mod(-40, 360)); // 320
System.out.println(mod(-400, 360)); // 320
}
}
请注意,当给定角度超过-360时有效。
答案 1 :(得分:4)
虽然您的解决方案可以解决问题,但算法实际上与Google使用的算法不同。如果使用负除数,它会有所不同。
public double GoogleModulo(double value, double divisor)
{
long q = (long)Math.Floor(value / divisor);
return value - q * divisor;
}
Console.WriteLine(GoogleModulo( 40, 360)); // 40
Console.WriteLine(GoogleModulo( -40, 360)); // 320
Console.WriteLine(GoogleModulo(-400, 360)); // 320
Console.WriteLine(GoogleModulo( 40, -360)); // -320
检查google对上一次计算的回复here。
该算法在wikipedia上解释,归功于Donald Knuth。
答案 2 :(得分:3)
这应该会给你所需的结果
public double Angle {
get { return _Angle; }
set { _Angle = value % 360 + (value % 360 < 0 : 360 : 0); }
}
我假设360度是度,你试图找到{0,360}角度所在的位置。
答案 3 :(得分:2)
mod操作非常慢。如果可能,请使用位掩码替换。
coobird的代码非常好......但是因为它正在进行mod操作而非常慢。如果可以将数据扩展到两个范围的某个幂,那么您可以通过使用位掩码将速度提高大约一个数量级(至少快2或3倍)。
C代码:
#define BIT_MASK (0xFFFF)
if (a < 0) {
return b + (a & BIT_MASK);
} else {
return a & BIT_MASK;
}
随意制作#define运行时的东西。并随意调整位掩码,使其成为您需要的两种功能。像0xFFFFFFFF或2的幂,你决定实施。
答案 4 :(得分:1)
// go 'round once
set { _Angle = (value + 360) % 360 }
答案 5 :(得分:-1)
(360 * Math.floor(Math.abs(value) / 360) + value) % 360
答案 6 :(得分:-1)
如果你的值不会超出范围,你可以做一点循环。
while (value < 0) {
value = value + 360;
}
while (value > 360) {
value = value - 360;
}