I have been trying to get this to work for 3 days, and I feel like I'm using the wrong approach, if anyone can correct me I will wax your car. Background, client asked to me make a simple pyramid algorithm. I want to select add everything to a list of objects and make everything on the left side true and everything on the right side false. Every other line reads the line 2 lines prior and adds multiple entries. The first time it adds a number like 1 it's one time, then it adds two 1's for each 1 until there is 4. So the first time it enters a 1 on line 1, then on line 3 it adds a 1 two times, then on line 5 it reads from line 3 and adds each of those 1's 2 times.
Here is a visual representation.
|1|
|2| |3|
|1|1| |4|5|
|2|2|3|3| |6|7|8|9|
|1|1|1|1|4|4|5|5| |10|11|12|13|14|15|16|17|
|2|2|2|2|3|3|3|3|6|6|7|7|8|8|9|9| |18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33
The order this list would be is:
1|2|3|1|1|4|5|2|2|3|3|6|7|8|9|1|1|1|1|4|4|5|5|10|11|12|13|14|15|16|17...
I keep getting close, but it fails to generate the correct output. `
for (int i = 1; i < 50; i = i * 2)
{
Response.Write(i.ToString() + " - ");
var previousLevel = (i / 2 / 2);
foreach (var oc in infoRows.Where(x => x.level == previousLevel))
{
for (int p = i; p > 0; p--)
{
Response.Write(oc.id + "*");
}
}
while (level <= i)
{
for (int r = 1; r <= i; r++)
{
InfoRow tempInforow = new InfoRow();
tempInforow.customerCode = GenerateCustomerNumber(position);
tempInforow.id = customerId;
tempInforow.sendtoidnumber = level.ToString();
tempInforow.status = 0; // GetStatus(position, totalCount);
tempInforow.position = position;
tempInforow.level = i;
infoRows.Add(tempInforow);
customerId++;
position++;
Response.Write(tempInforow.id + "-");
level++;
}
}
}
`
Essentially this generates the following:
1 - 1-
2 - 2-3-
4 - 1*1*1*1*4-5-6-7-
8 - 2*2*2*2*2*2*2*2*3*3*3*3*3*3*3*3*8-9-10-11-12-13-14-15-
16 - 4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7*16-17-18-19-20-21-22-23-24-25-26-27-28-29-30-31-
32 -
I've tried 30 different ways with switch statements, while statements, for and foreach statements, the closest I can get to this working is level 4.
Can someone suggest another way. Maybe a multidimensional array or idk what. Thank you.
Let's write the sequence down and have a look on what's going on:
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ...
seq 1 2 3 1 1 4 5 2 2 3 3 6 7 8 9 1 1 1 1 4 4 5 5 10 ...
^ ^ ^ ^ ^ ^
| |
if # is power of 2 (e.g. 8 == 2**3)
we should copy and double # / 4 items (here 8 / 4 == 2 items)
starting from # / 4 item (here 8 / 4 == 2, starting from item #2)
Time to implement this algorithm
Code:
using System.Linq;
...
private static List<int> Pyramid(int size) {
if (size < 0)
throw new ArgumentOutOfRangeException(nameof(size));
if (size <= 3)
return Enumerable.Range(1, size).ToList();
List<int> result = new List<int>(size) { 1, 2, 3 };
for (int value = 4; result.Count < size; )
if (BitOperations.IsPow2(result.Count + 1)) {
int chunk = (result.Count + 1) / 4;
for (int i = 0; i < chunk && result.Count < size; ++i) {
result.Add(result[chunk - 1 + i]);
if (result.Count >= size)
return result;
result.Add(result[chunk - 1 + i]);
}
}
else
result.Add(value++);
return result;
}
Demo:
// First 31 items from the pyramid
Console.Write(string.Join("|", Pyramid(31)));
Output:
1|2|3|1|1|4|5|2|2|3|3|6|7|8|9|1|1|1|1|4|4|5|5|10|11|12|13|14|15|16|17
I'm playing around with numbers, and I'm looking to write a small program that will return the largest double-digit of an integer that's passed in for example:
I pass in 2215487
it should return 87
I pass in 98765499
It should return 99
I've tried looking at Math.Max, but I don't believe that's what I'm looking for unless I have overlooked it
You can divide by 10 each time and then compare the remainder of dividing the remaining number by 100. For example:
int v = 98765499;
int m = 0;
v = Math.Abs(v); // negate negative numbers so that we can process these too
while (v >= 10) // if you want to accept single digit initial values for V change this to v > 0
{
m = Math.Max(m, v % 100);
v /= 10;
}
Console.WriteLine(m);
We use v >= 10 because we don't want to consider single-digit numbers (e.g. an initial value of v = 5).
v % 100 uses the remainder operator to give us the value left over when we divide by 100.
v /= 10 divides v by 10 and stores the result in v.
I've used Math.Abs( ) to make this work with negative numbers too, though you can take this line out if you only care about positive numbers.
At the end, m will either hold 0 (for single digit numbers or zero) or the highest two-digit value.
Example execution flow:
Initial V
V % 100
New V
98765499
99
9876549
9876549
49
987654
987654
54
98765
98765
65
9876
9876
76
987
987
87
98
98
98
9
Highest v % 100 is 99.
Try it online
A very simple solution would be as follows:
var thenumber = 987654990;
var s = thenumber.ToString();
var max = 0;
for (var i = 0; i < s.Length-1; i++) {
int d1 = (int)(s[i] - '0');
int d2 = (int)(s[i+1] - '0');
max = Math.Max(max, 10*d1+ d2);
}
Console.WriteLine(max);
Ie, just iterate over the number and calculate the "pair" at the current position (consisting of the current digit d1 and the next one d2) if the pair is greater than the current max, make it the new max ...
Consider this method that works well:
public static bool mightBePrime(int N) {
BigInteger a = rGen.Next (1, N-1);
return modExp (a, N - 1, N) == 1;
}
Now, in order to fulfill a requirement of the class I'm taking, mightBePrime must accept a BigInteger N, but that means that I need a different way to generate my random BigInteger a.
My first idea was to do something like BigInteger a = (N-1) * rGen.NextDouble (), but a BigInteger can't be multiplied by a double.
How can I generate a random BigInteger between 1 and N-1, where N is a BigInteger?
Paul suggested in a comment that I generate a number using random bytes, then throw it away if it's too big. Here's what I came up with (Marcel's answer + Paul's advice):
public static BigInteger RandomIntegerBelow(BigInteger N) {
byte[] bytes = N.ToByteArray ();
BigInteger R;
do {
random.NextBytes (bytes);
bytes [bytes.Length - 1] &= (byte)0x7F; //force sign bit to positive
R = new BigInteger (bytes);
} while (R >= N);
return R;
}
http://amirshenouda.wordpress.com/2012/06/29/implementing-rsa-c/ helped a little too.
Use the Random-Class
public BigInteger getRandom(int length){
Random random = new Random();
byte[] data = new byte[length];
random.NextBytes(data);
return new BigInteger(data);
}
The naive implementation will fail on average 64 times before finding a valid BigInteger within the specified range.
On the worst case, my implementation will retry on average only 0.5 times (read as: 50% of the times it will find a result on the first try).
Also, unlike with modular arithmetic, my implementation maintains a uniform distribution.
Explanation
We must generate a random BigInteger between min and max.
If min > max, we swap min with max
To simplify the implementation we shift our range from [min, max] to [0, max-min], this way we won't have to deal with the sign bit
We count how many bytes max contains (bytes.Length)
From the most significant bit, we count how many bits are 0 (zeroBits)
We generate a random sequence of bytes.Length bytes
We know that for our sequence to be < max, at least zeroBits bits from the most significant bit must be 0, so we use a zeroBitMask to set them with a single bit-to-bit & operation over the most significant byte, this will save a lot of time by reducing the change of generating a number out of our range
We check if the number we generated is > max, and if so we try again
We unshift the range back from [0, max-min] to [min, max] by adding min to our result
And we have our number. 😊
Implementation
public static BigInteger RandomInRange(RandomNumberGenerator rng, BigInteger min, BigInteger max)
{
if (min > max)
{
var buff = min;
min = max;
max = buff;
}
// offset to set min = 0
BigInteger offset = -min;
min = 0;
max += offset;
var value = randomInRangeFromZeroToPositive(rng, max) - offset;
return value;
}
private static BigInteger randomInRangeFromZeroToPositive(RandomNumberGenerator rng, BigInteger max)
{
BigInteger value;
var bytes = max.ToByteArray();
// count how many bits of the most significant byte are 0
// NOTE: sign bit is always 0 because `max` must always be positive
byte zeroBitsMask = 0b00000000;
var mostSignificantByte = bytes[bytes.Length - 1];
// we try to set to 0 as many bits as there are in the most significant byte, starting from the left (most significant bits first)
// NOTE: `i` starts from 7 because the sign bit is always 0
for (var i = 7; i >= 0; i--)
{
// we keep iterating until we find the most significant non-0 bit
if ((mostSignificantByte & (0b1 << i)) != 0)
{
var zeroBits = 7 - i;
zeroBitsMask = (byte)(0b11111111 >> zeroBits);
break;
}
}
do
{
rng.GetBytes(bytes);
// set most significant bits to 0 (because `value > max` if any of these bits is 1)
bytes[bytes.Length - 1] &= zeroBitsMask;
value = new BigInteger(bytes);
// `value > max` 50% of the times, in which case the fastest way to keep the distribution uniform is to try again
} while (value > max);
return value;
}
Test
using (var rng = RandomNumberGenerator.Create())
{
BigInteger min = 0;
BigInteger max = 5;
var attempts = 10000000;
var count = new int[(int)max + 1];
var sw = Stopwatch.StartNew();
for (var i = 0; i < attempts; i++)
{
var v = BigIntegerUtils.RandomInRange(rng, min, max);
count[(int)v]++;
}
var time = sw.Elapsed;
Console.WriteLine("Generated {0} big integers from {1} to {2} in {3}", attempts, min, max, time);
Console.WriteLine("On average: {0} ms/integer or {1} integers/second", time.TotalMilliseconds / attempts, attempts / time.TotalSeconds);
for (var i = 0; i <= max; i++)
Console.WriteLine("{0} generated {1}% of the times ({2} times)", i, count[i] * 100d / attempts, count[i]);
}
Test output on my i7-6500U:
Generated 10000000 big integers from 0 to 5 in 00:00:09.5413677
On average: 0.00095413677 ms/integer or 1048067.77334449 integers/second
0 generated 16.66633% of the times (1666633 times)
1 generated 16.6717% of the times (1667170 times)
2 generated 16.66373% of the times (1666373 times)
3 generated 16.6666% of the times (1666660 times)
4 generated 16.68271% of the times (1668271 times)
5 generated 16.64893% of the times (1664893 times)
Another test output on my i7-6500U
Generated 10000000 big integers from 0 to 10^100 in 00:00:17.5036570
On average: 0.0017503657 ms/integer or 571309.184132207 integers/second
Here is a NextBigInteger extension method for the Random class. It is based on the excellent Fabio Iotti's implementation, modified for succinctness.
/// <summary>
/// Returns a random BigInteger that is within a specified range.
/// The lower bound is inclusive, and the upper bound is exclusive.
/// </summary>
public static BigInteger NextBigInteger(this Random random,
BigInteger minValue, BigInteger maxValue)
{
if (minValue > maxValue) throw new ArgumentException();
if (minValue == maxValue) return minValue;
BigInteger zeroBasedUpperBound = maxValue - 1 - minValue; // Inclusive
Debug.Assert(zeroBasedUpperBound.Sign >= 0);
byte[] bytes = zeroBasedUpperBound.ToByteArray();
Debug.Assert(bytes.Length > 0);
Debug.Assert((bytes[bytes.Length - 1] & 0b10000000) == 0);
// Search for the most significant non-zero bit
byte lastByteMask = 0b11111111;
for (byte mask = 0b10000000; mask > 0; mask >>= 1, lastByteMask >>= 1)
{
if ((bytes[bytes.Length - 1] & mask) == mask) break; // We found it
}
while (true)
{
random.NextBytes(bytes);
bytes[bytes.Length - 1] &= lastByteMask;
var result = new BigInteger(bytes);
Debug.Assert(result.Sign >= 0);
if (result <= zeroBasedUpperBound) return result + minValue;
}
}
The percentage of BigInteger instances that are discarded, in order to return a value within the desirable range, is 30% on average (best case 0%, worst case 50%).
The distribution of random numbers is uniform.
Usage example:
Random random = new();
BigInteger value = random.NextBigInteger(BigInteger.Zero, new BigInteger(1000));
Note: The structure of the bytes returned from the BigInteger.ToByteArray is well documented (in the Remarks section), so it should be fairly safe to assume that the BigInteger's byte[] representation is not going to change in future versions of the .NET platform. In case that happened, the above NextBigInteger implementation could fail in nasty ways, like entering an infinite loop or generating numbers within a wrong range. I've added some debugging assertions that should never fail with the current representation, but the coverage of checking for invalid conditions is by no means thorough.
Here's an alternate way to generate numbers within range without throwing away values and allowing BigIntegers for min and max.
public BigInteger RandomBigInteger(BigInteger min, BigInteger max)
{
Random rnd = new Random();
string numeratorString, denominatorString;
double fraction = rnd.NextDouble();
BigInteger inRange;
//Maintain all 17 digits of precision,
//but remove the leading zero and the decimal point;
numeratorString = fraction.ToString("G17").Remove(0, 2);
//Use the length instead of 17 in case the random
//fraction ends with one or more zeros
denominatorString = string.Format("1E{0}", numeratorString.Length);
inRange = (max - min) * BigInteger.Parse(numeratorString) /
BigInteger.Parse(denominatorString,
System.Globalization.NumberStyles.AllowExponent)
+ min;
return inRange;
}
For generality you may want to specify precision as well. This seems to work.
public BigInteger RandomBigIntegerInRange(BigInteger min, BigInteger max, int precision)
{
Random rnd = new Random();
string numeratorString, denominatorString;
double fraction = rnd.NextDouble();
BigInteger inRange;
numeratorString = GenerateNumeratorWithSpecifiedPrecision(precision);
denominatorString = string.Format("1E{0}", numeratorString.Length);
inRange = (max - min) * BigInteger.Parse(numeratorString) / BigInteger.Parse(denominatorString, System.Globalization.NumberStyles.AllowExponent) + min;
return inRange;
}
private string GenerateNumeratorWithSpecifiedPrecision(int precision)
{
Random rnd = new Random();
string answer = string.Empty;
while(answer.Length < precision)
{
answer += rnd.NextDouble().ToString("G17").Remove(0, 2);
}
if (answer.Length > precision) //Most likely
{
answer = answer.Substring(0, precision);
}
return answer;
}
For my use case, I did the following:
Random rnd = new Random();
BigInteger myVal = rnd.NextBigInteger(50,100); //returns a 50-99 bit BigInteger
The code:
/// <summary>
/// Returns a random BigInteger with a minimum bit count between <paramref name="minBitLength"/>(inclusive) and <paramref name="maxBitLength"/>(exclusive).
/// </summary>
/// <param name="minBitLength">The inclusive lower bit length of the random BigInteger returned.</param>
/// <param name="maxBitLength">The exclusive upper bit length of the random BigInteger returned. <paramref name="maxBitLength"/> must be greater than or equal to minValue.</param>
public static BigInteger NextBigInteger(this Random rnd, int minBitLength, int maxBitLength)
{
if (minBitLength < 0) throw new ArgumentOutOfRangeException();
int bits = rnd.Next(minBitLength, maxBitLength);
if (bits == 0) return BigInteger.Zero;
byte[] bytes = new byte[(bits + 7) / 8];
rnd.NextBytes(bytes);
// For the top byte, place a leading 1-bit then downshift to achieve desired length.
bytes[^1] = (byte)((0x80 | bytes[^1]) >> (7 - (bits - 1) % 8));
return new BigInteger(bytes, true);
}
Example Results:
____Example Lengths___ ___Example Results___
NextBigInteger(0,0) ==> 0 0 0 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0
NextBigInteger(0,1) ==> 0 0 0 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0
NextBigInteger(0,2) ==> 1 1 1 0 1 0 0 1 0 0 1 | 1 1 1 1 0 1 0
NextBigInteger(0,3) ==> 2 2 2 1 2 0 0 0 1 0 2 | 0 1 0 2 0 1 2
NextBigInteger(0,4) ==> 3 2 0 3 0 0 0 3 1 3 3 | 0 1 1 0 3 1 0
NextBigInteger(0,5) ==> 1 4 1 2 4 1 2 0 3 1 2 | 1 1 10 10 14 11 8
NextBigInteger(0,6) ==> 3 5 1 1 5 5 3 5 1 4 3 | 0 0 1 3 2 7 27
NextBigInteger(1,1) ==> 1 1 1 1 1 1 1 1 1 1 1 | 1 1 1 1 1 1 1
NextBigInteger(1,2) ==> 1 1 1 1 1 1 1 1 1 1 1 | 1 1 1 1 1 1 1
NextBigInteger(1,3) ==> 2 1 2 1 2 2 2 2 1 1 1 | 1 1 1 1 2 2 3
NextBigInteger(1,4) ==> 1 2 3 3 2 1 1 2 2 2 1 | 7 3 1 1 6 1 5
NextBigInteger(1,5) ==> 4 3 1 2 3 1 4 4 1 1 3 | 1 3 1 6 6 12 7
NextBigInteger(1,6) ==> 5 5 4 1 1 2 3 2 1 1 1 | 1 28 7 5 25 15 13
NextBigInteger(2,2) ==> 2 2 2 2 2 2 2 2 2 2 2 | 2 2 3 2 3 2 3
NextBigInteger(2,3) ==> 2 2 2 2 2 2 2 2 2 2 2 | 2 2 3 2 2 3 3
NextBigInteger(2,4) ==> 3 3 2 3 3 3 3 3 3 2 3 | 3 2 7 6 3 3 3
NextBigInteger(2,5) ==> 2 4 2 2 4 4 2 2 4 3 2 | 6 3 13 2 6 4 11
NextBigInteger(2,6) ==> 5 3 5 3 2 3 2 4 4 5 3 | 2 3 17 2 27 14 18
NextBigInteger(3,3) ==> 3 3 3 3 3 3 3 3 3 3 3 | 4 4 5 7 6 7 4
NextBigInteger(3,4) ==> 3 3 3 3 3 3 3 3 3 3 3 | 6 5 4 7 6 4 6
NextBigInteger(3,5) ==> 3 3 3 3 4 4 4 4 3 4 4 | 6 10 12 6 6 15 7
NextBigInteger(3,6) ==> 4 4 3 3 3 4 3 5 4 3 4 | 28 22 5 11 25 8 6
NextBigInteger(4,4) ==> 4 4 4 4 4 4 4 4 4 4 4 | 12 8 8 9 8 10 13
NextBigInteger(4,5) ==> 4 4 4 4 4 4 4 4 4 4 4 | 15 10 10 8 14 8 13
NextBigInteger(4,6) ==> 5 5 5 5 4 5 5 4 5 5 5 | 15 13 14 31 19 15 21
Some Random Stuff:
One issue with many large random number generators is they can produce output that are all similar in scale to the maxValue. Example: if we had something like RandomBigIntegerUsingValues(min: 100, max:999999999999999) then 99% of our results will be between 9999999999999 and 999999999999999. The odds of getting something under 1000000 are 1 in 1000000000.
Some range checking is implicitly handled by the Random.Next().
Matched .net libraries extension methods as best as possible so the name NextBigInteger() was used since it matches Random's built-in NextSingle(), NextDouble(), NextInt64() naming. And also .net's Random signature was was used: minBitLength(inclusive), maxBitLength(exclusive).
Releasing under the MIT License.
The following Range method will return an IEnumerable<BigInteger> within the range you specify.
A simple Extension method will return a random element within the IEnumerable.
public static IEnumerable<BigInteger> Range(BigInteger from, BigInteger to)
{
for(BigInteger i = from; i < to; i++) yield return i;
}
public static class Extensions
{
public static BigInteger RandomElement(this IEnumerable<BigInteger> enumerable, Random rand)
{
int index = rand.Next(0, enumerable.Count());
return enumerable.ElementAt(index);
}
}
usage:
Random rnd = new Random();
var big = Range(new BigInteger(10000000000000000), new BigInteger(10000000000000020)).RandomElement(rnd);
// returns random values and in this case it was 10000000000000003
This question already has answers here:
Returning the nearest multiple value of a number
(6 answers)
Closed 3 years ago.
I am trying to figure out how to round prices - both ways. For example:
Round down
43 becomes 40
143 becomes 140
1433 becomes 1430
Round up
43 becomes 50
143 becomes 150
1433 becomes 1440
I have the situation where I have a price range of say:
£143 - £193
of which I want to show as:
£140 - £200
as it looks a lot cleaner
Any ideas on how I can achieve this?
I would just create a couple methods;
int RoundUp(int toRound)
{
if (toRound % 10 == 0) return toRound;
return (10 - toRound % 10) + toRound;
}
int RoundDown(int toRound)
{
return toRound - toRound % 10;
}
Modulus gives us the remainder, in the case of rounding up 10 - r takes you to the nearest tenth, to round down you just subtract r. Pretty straight forward.
You don't need to use modulus (%) or floating point...
This works:
public static int RoundUp(int value)
{
return 10*((value + 9)/10);
}
public static int RoundDown(int value)
{
return 10*(value/10);
}
This code rounds to the nearest multiple of 10:
int RoundNum(int num)
{
int rem = num % 10;
return rem >= 5 ? (num - rem + 10) : (num - rem);
}
Very simple usage :
Console.WriteLine(RoundNum(143)); // prints 140
Console.WriteLine(RoundNum(193)); // prints 190
A general method to round a number to a multiple of another number, rounding away from zero.
For integer
int RoundNum(int num, int step)
{
if (num >= 0)
return ((num + (step / 2)) / step) * step;
else
return ((num - (step / 2)) / step) * step;
}
For float
float RoundNum(float num, float step)
{
if (num >= 0)
return floor((num + step / 2) / step) * step;
else
return ceil((num - step / 2) / step) * step;
}
I know some parts might seem counter-intuitive or not very optimized. I tried casting (num + step / 2) to an int, but this gave wrong results for negative floats ((int) -12.0000 = -11 and such). Anyways these are a few cases I tested:
any number rounded to step 1 should be itself
-3 rounded to step 2 = -4
-2 rounded to step 2 = -2
3 rounded to step 2 = 4
2 rounded to step 2 = 2
-2.3 rounded to step 0.2 = -2.4
-2.4 rounded to step 0.2 = -2.4
2.3 rounded to step 0.2 = 2.4
2.4 rounded to step 0.2 = 2.4
Divide the number by 10.
number = number / 10;
Math.Ceiling(number);//round up
Math.Round(number);//round down
Then multiply by 10.
number = number * 10;
public static int Round(int n)
{
// Smaller multiple
int a = (n / 10) * 10;
// Larger multiple
int b = a + 10;
// Return of closest of two
return (n - a > b - n) ? b : a;
}
Today I was writing a program in C#, and I used % to calculate some index... My program didn't work, so I debugged it and I realized that "%" is not working like in other program languages that I know.
For example:
In Python % returns values like this:
for x in xrange (-5, 6):
print x, "% 5 =", x % 5
-5 % 5 = 0
-4 % 5 = 1
-3 % 5 = 2
-2 % 5 = 3
-1 % 5 = 4
0 % 5 = 0
1 % 5 = 1
2 % 5 = 2
3 % 5 = 3
4 % 5 = 4
5 % 5 = 0
In C#:
for (int i = -5; i < 6; i++)
{
Console.WriteLine(i + " % 5 = " + i % 5);
}
-5 % 5 = 0
-4 % 5 = -4
-3 % 5 = -3
-2 % 5 = -2
-1 % 5 = -1
0 % 5 = 0
1 % 5 = 1
2 % 5 = 2
3 % 5 = 3
4 % 5 = 4
5 % 5 = 0
Did I do something wrong or is % not working like it should?
As explained in the comments, the different behaviour is by design. The different languages just ascribe different meanings to the % operator.
You ask:
How can I use modulus operator in C#?
You can define a modulus operator yourself that behaves the same way as the Python % operator:
int mod(int a, int n)
{
int result = a % n;
if ((result<0 && n>0) || (result>0 && n<0)) {
result += n;
}
return result;
}
Both answers are correct. Although personally I think the "always positive" one makes more sense.
You can define your own modulus function that only gives positive answers like this:
int mod(int a, int n) {
return ((a%n)+n) % n;
}
In modular arithmetic, one defines classes of numbers based on the modulo. In other words, in modulo m arithmetic, a number n is equivalent (read: the same) to n + m, n - m, n + 2m, n - 2m, etc.
One defines m "baskets" and every number falls in one (and only one) of them.
Example: one can say "It's 4:30 pm" or one can say "It's 16:30". Both forms mean exactly the same time, but are different representations of it.
Thus both, the Python and C# results are correct! The numbers are the same in the modulo 5 arithmetic you chose. It would also have been mathematically correct to return (5, 6, 7, 8, 9) for example. Just a bit odd.
As for the choice of representation (in other words, the choice on how to represent negative numbers), that is just a case of different design choices between the two languages.
However, that is not at all what the % operator actually does in C#. The % operator is not the canonical modulus operator; it is the remainder operator. The A % B operator actually answer the question "If I divided A by B using integer arithmetic, what would the remainder be?"
— What's the difference? Remainder vs Modulus by Eric Lippert
Quick snippet to get the canonical modulus:
return ((n % m) + m) % m;
Test implementation:
Mono/C#:
machine:~ user$ cat mod.cs
using System;
public class Program
{
public static void Main (string[] args)
{
Console.WriteLine(Mod(-2, 5));
Console.WriteLine(Mod(-5, 5));
Console.WriteLine(Mod(-2, -5));
}
public static int Mod (int n, int m)
{
return ((n % m) + m) % m;
}
}
machine:~ user$ mono mod.exe
3
0
-2
Python:
machine:~ user$ cat mod.py
print -2%5;
print -5%5;
print -2%-5;
machine:~ user$ python mod.py
3
0
-2