Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C#, how do I implement modulus like google calc does?

Tags:

c#

modulo

I have a class which represents a shape. The Shape class has a property called Angle. I want the setter for this property to automatically wrap the value into the range [0,359].

Unfortunately, a simple _Angle = value % 360; only works for positive numbers. In C#, -40 % 360 == -40. Google calc does it the way I want it. The value should be 320.

What's the most elegant solution in C#?

Here's the best way I've got so far:

     public double Angle {
        get { return _Angle; } 
        set {
            if ( value >= 0 ) {
                _Angle = value % 360;
            }
            else {
                _Angle = value - (360 * ((int)(value / 360) - 1)); 
            }
        }
    }

Edit:

Thanks guys, I now have:

     public double Angle {
        get { return _Angle; } 
        set {
            _Angle = (value % 360) + ((value < 0) ? 360 : 0);
        }
    }

..Which is a lot better :)

like image 875
Blorgbeard Avatar asked Jan 26 '09 02:01

Blorgbeard


2 Answers

Although this is for Java, Java also has the same behavior for modulus. (i.e. -40 % 360 == -40).

The below code should return an answer from [0. 360), regardless of the given angle, positive or negative.

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
    }
}

Note that works when the given angle is past -360.

like image 73
coobird Avatar answered Nov 08 '22 14:11

coobird


While your solution works for the problem you have the algorithm is actually not identical to the one used by Google. It differs if you use a negative divisor.

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

Check google's response to the last calculation here.

The algorithm is explained on wikipedia and attributed to Donald Knuth.

like image 26
Jesper Larsen-Ledet Avatar answered Nov 08 '22 13:11

Jesper Larsen-Ledet