What is an efficient way to check if a Int32 n is a Mersenne prime?
This is my attempt :
Apparently this code returns true for some numbers which are a Mersenne prime e.g. 31 but it doesn't for others such as 127.
Can somebody tell me whats wrong with my code?
/// <summary>
/// Checks if a nubmer is a mersenne prime
/// </summary>
/// <param name="candidate"></param>
/// <returns></returns>
public static bool IsMersennePrime(uint n)
{
var x = Math.Pow(2, n) - 1;
return IsPrime((uint)x);
}
/// <summary>
/// Checks if a nubmer is a prime
/// </summary>
/// <param name="candidate"></param>
/// <returns>true if number is a prime false if its not a prime</returns>
private static bool IsPrime(uint candidate)
{
//
// Test whether the parameter is a prime number.
//
if ((candidate & 1) == 0)
{
if (candidate == 2)
{
return true;
}
else
{
return false;
}
}
int num = (int)Math.Sqrt((double)candidate);
for (int i = 3; i <= num; i += 2)
{
if ((candidate % i) == 0)
{
return false;
}
}
return true;
}
Since you just want Mersenne primes which fits into an uint the best way is to check against actual values. Read more about A000043 and A000668.
private static int[] A000043 = new int[] { 2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937, 21701, 23209, 44497, 86243, 110503, 132049, 216091, 756839, 859433, 1257787, 1398269, 2976221, 3021377, 6972593, 13466917, 20996011, 24036583, 25964951, 30402457, 32582657 };
private static int[] A000668 = new int[] { 3, 7, 31, 127, 8191, 131071, 524287, 2147483647 };
public static bool IsInA000668(int value) => A000668.Contains(value);
public static bool IsInA000043(int value) => A000043.Contains(value);
Related
so for example, this code here does the job fine for this specific task, but I really don't like how I need to reuse the loop 2 times to get the size and then implement the method, it feels not right.
public static int[] FilterByDigit(int[] source, int digit)
{
int size = 0;
for (int i = 0; i < source.Length; i++)
{
bool result = source[i].ToString().Contains(digit.ToString());
if (result)
{
size++;
}
}
int[] arr = new int[size];
int count = 0;
for (int i = 0; i < source.Length; i++)
{
bool result = source[i].ToString().Contains(digit.ToString());
if (result)
{
arr[count] = source[i];
count++;
}
}
return arr;
}
Is there anyway to get the size in the first loop and then implement the method, having no need of the second loop?
If you need to understand this particular task:
/// <summary>
/// Returns new array of elements that contain expected digit from source array.
/// </summary>
/// <param name="source">Source array.</param>
/// <param name="digit">Expected digit.</param>
/// <returns>Array of elements that contain expected digit.</returns>
/// <exception cref="ArgumentNullException">Thrown when array is null.</exception>
/// <exception cref="ArgumentException">Thrown when array is empty.</exception>
/// <exception cref="ArgumentOutOfRangeException">Thrown when digit value is out of range (0..9).</exception>
/// <example>
/// {1, 2, 3, 4, 5, 6, 7, 68, 69, 70, 15, 17} => { 7, 70, 17 } for digit = 7.
/// </example>
try this
public static int[] FilterByDigit(int[] source, int digit)
{
return source.Where(s => s.ToString().Contains(digit.ToString()));
}
output
int digit=7;
var source = new int[] {1, 2, 3, 4, 5, 6, 7, 68, 69, 70, 15, 17};
var result =FilterByDigit(source,digit);
var output=string.Join(",",result);
7,70,17
I'm just lost and can't seem to know what to do to calculate the simple moving average?
This is one of the method in the file which is used to calculate the simple moving average.
public async Task<decimal?> UpdateAsync(decimal? value, CancellationToken cancelToken)
{
await Task.Run(() =>
{
var av = default(decimal?);
if (_av.Count - 1 >= _p)
{
}
else
{
av = value;
}
_av.Add(av);
return av;
}, cancelToken).ConfigureAwait(false);
throw new Exception("major issue");
}
}
Let's start with the question:
I'm just lost and can't seem to know what to do to calculate the
simple moving average?
Given
public static class Extensions
{
public static IEnumerable<decimal> MovingAvg(this IEnumerable<decimal> source, int period)
{
var buffer = new Queue<decimal>();
foreach (var value in source)
{
buffer.Enqueue(value);
// sume the buffer for the average at any given time
yield return buffer.Sum() / buffer.Count;
// Dequeue when needed
if (buffer.Count == period)
buffer.Dequeue();
}
}
}
Usage
static void Main(string[] args)
{
var input = new decimal[] { 1, 2, 2, 4, 5, 6, 6, 6, 9, 10, 11, 12, 13, 14, 15 };
var result = input.MovingAvg(2);
Console.WriteLine(string.Join(", ",result));
}
Output
1, 1.5, 2, 3, 4.5, 5.5, 6, 6, 7.5, 9.5, 10.5, 11.5, 12.5, 13.5, 14.5
So first of all what is moving average
A simple moving average is a method for computing an average of a stream of numbers by only averaging the last P numbers from the stream, where P is known as the period.
Next is the code as how I imagined my moving average to be implemented. It is possible to use LINQ but at each and every step after we add a number I want my Average to be updated.
My code is heavily commented so please read the comments.
public class MovingAverageCalculator {
/// <summary>
/// Maximum number of numbers this moving average calculator can hold.
/// </summary>
private readonly int maxElementCount;
/// <summary>
/// Numbers which will be used for calculating moving average.
/// </summary>
private readonly int[] currentElements;
/// <summary>
/// At which index the next number will be added.
/// </summary>
private int currentIndex;
/// <summary>
/// How many elements are there currently in this moving average calculator.
/// </summary>
private int currentElementCount;
/// <summary>
/// Current total of all the numbers that are being managed by this moving average calculator
/// </summary>
private double currentTotal;
/// <summary>
/// Current Average of all the numbers.
/// </summary>
private double currentAvg;
/// <summary>
/// An object which can calcauclate moving average of given numbers.
/// </summary>
/// <param name="period">Maximum number elements</param>
public MovingAverageCalculator(int period) {
maxElementCount = period;
currentElements = new int[maxElementCount];
currentIndex = 0;
currentTotal = 0;
currentAvg = 0;
}
/// <summary>
/// Adds an item to the moving average series then updates the average.
/// </summary>
/// <param name="number">Number to add.</param>
public void AddElement(int number){
// You can only have at most maximum elements in your moving average series.
currentElementCount = Math.Min(++currentElementCount, maxElementCount);
// IF your current index reached the maximum allowable number then you must reset
if (currentIndex == maxElementCount){
currentIndex = 0;
}
// Copy the current index number to the local variable
var temp = currentElements[currentIndex];
// Substract the value from the current total because it will be replaced by the added number.
currentTotal -= temp;
// Add the number to the current index
currentElements[currentIndex] = number;
// Increase the total by the added number.
currentTotal += number;
// Increase index
currentIndex++;
// Calculate average
currentAvg = (double)currentTotal / currentElementCount;
}
/// <summary>
/// Gets the current average
/// </summary>
/// <returns>Average</returns>
public double GetAverage() => currentAvg;
}
And lastly, I checked your code but It does not make sense to me
I am using following code to implement Luhn algorithm for credit card check in C# language, but could not get the output to generate the check sum its showing validity. Kindly help me. Thank you in advance.
public class Program
{
private static void Main(string[]creditcard)
{
int sum = 0, d;
string num ="7992739871";
int a = 0;
for (int i = num.Length - 2; i >= 0; i--)
{
d = Convert.ToInt32(num.Substring(i, 1));
if (a % 2 == 0)
d = d * 2;
if (d > 9)
d -= 9;
sum += d;
a++;
}
if ((10 - (sum % 10) == Convert.ToInt32(num.Substring(num.Length - 1))))
Console.WriteLine("valid");
Console.WriteLine("sum of digits of the number" + sum);
}
}
Here are some extension methods that compute a Luhn checkdigit, validate a number with a checkdigit, and add a checkdigit to a number. Tested in .NET 4.5.
There are extension methods for strings, ints, int64s and IList.
I got some ideas for this from rosettacode.org
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
public static class CheckDigitExtension
{
static readonly int[] Results = { 0, 2, 4, 6, 8, 1, 3, 5, 7, 9 };
#region extension methods for IList<int>
/// <summary>
/// For a list of digits, compute the ending checkdigit
/// </summary>
/// <param name="digits">The list of digits for which to compute the check digit</param>
/// <returns>the check digit</returns>
public static int CheckDigit(this IList<int> digits)
{
var i = 0;
var lengthMod = digits.Count%2;
return (digits.Sum(d => i++ % 2 == lengthMod ? d : Results[d]) * 9) % 10;
}
/// <summary>
/// Return a list of digits including the checkdigit
/// </summary>
/// <param name="digits">The original list of digits</param>
/// <returns>the new list of digits including checkdigit</returns>
public static IList<int> AppendCheckDigit(this IList<int> digits)
{
var result = digits;
result.Add(digits.CheckDigit());
return result;
}
/// <summary>
/// Returns true when a list of digits has a valid checkdigit
/// </summary>
/// <param name="digits">The list of digits to check</param>
/// <returns>true/false depending on valid checkdigit</returns>
public static bool HasValidCheckDigit(this IList<int> digits)
{
return digits.Last() == CheckDigit(digits.Take(digits.Count - 1).ToList());
}
#endregion extension methods for IList<int>
#region extension methods for strings
/// <summary>
/// Internal conversion function to convert string into a list of ints
/// </summary>
/// <param name="digits">the original string</param>
/// <returns>the list of ints</returns>
private static IList<int> ToDigitList(this string digits)
{
return digits.Select(d => d - 48).ToList();
}
/// <summary>
/// For a string of digits, compute the ending checkdigit
/// </summary>
/// <param name="digits">The string of digits for which to compute the check digit</param>
/// <returns>the check digit</returns>
public static string CheckDigit(this string digits)
{
return digits.ToDigitList().CheckDigit().ToString(CultureInfo.InvariantCulture);
}
/// <summary>
/// Return a string of digits including the checkdigit
/// </summary>
/// <param name="digits">The original string of digits</param>
/// <returns>the new string of digits including checkdigit</returns>
public static string AppendCheckDigit(this string digits)
{
return digits + digits.CheckDigit();
}
/// <summary>
/// Returns true when a string of digits has a valid checkdigit
/// </summary>
/// <param name="digits">The string of digits to check</param>
/// <returns>true/false depending on valid checkdigit</returns>
public static bool HasValidCheckDigit(this string digits)
{
return digits.ToDigitList().HasValidCheckDigit();
}
#endregion extension methods for strings
#region extension methods for integers
/// <summary>
/// Internal conversion function to convert int into a list of ints, one for each digit
/// </summary>
/// <param name="digits">the original int</param>
/// <returns>the list of ints</returns>
private static IList<int> ToDigitList(this int digits)
{
return digits.ToString(CultureInfo.InvariantCulture).Select(d => d - 48).ToList();
}
/// <summary>
/// For an integer, compute the ending checkdigit
/// </summary>
/// <param name="digits">The integer for which to compute the check digit</param>
/// <returns>the check digit</returns>
public static int CheckDigit(this int digits)
{
return digits.ToDigitList().CheckDigit();
}
/// <summary>
/// Return an integer including the checkdigit
/// </summary>
/// <param name="digits">The original integer</param>
/// <returns>the new integer including checkdigit</returns>
public static int AppendCheckDigit(this int digits)
{
return digits * 10 + digits.CheckDigit();
}
/// <summary>
/// Returns true when an integer has a valid checkdigit
/// </summary>
/// <param name="digits">The integer to check</param>
/// <returns>true/false depending on valid checkdigit</returns>
public static bool HasValidCheckDigit(this int digits)
{
return digits.ToDigitList().HasValidCheckDigit();
}
#endregion extension methods for integers
#region extension methods for int64s
/// <summary>
/// Internal conversion function to convert int into a list of ints, one for each digit
/// </summary>
/// <param name="digits">the original int</param>
/// <returns>the list of ints</returns>
private static IList<int> ToDigitList(this Int64 digits)
{
return digits.ToString(CultureInfo.InvariantCulture).Select(d => d - 48).ToList();
}
/// <summary>
/// For an integer, compute the ending checkdigit
/// </summary>
/// <param name="digits">The integer for which to compute the check digit</param>
/// <returns>the check digit</returns>
public static int CheckDigit(this Int64 digits)
{
return digits.ToDigitList().CheckDigit();
}
/// <summary>
/// Return an integer including the checkdigit
/// </summary>
/// <param name="digits">The original integer</param>
/// <returns>the new integer including checkdigit</returns>
public static Int64 AppendCheckDigit(this Int64 digits)
{
return digits * 10 + digits.CheckDigit();
}
/// <summary>
/// Returns true when an integer has a valid checkdigit
/// </summary>
/// <param name="digits">The integer to check</param>
/// <returns>true/false depending on valid checkdigit</returns>
public static bool HasValidCheckDigit(this Int64 digits)
{
return digits.ToDigitList().HasValidCheckDigit();
}
#endregion extension methods for int64s
}
Here are some XUnit test cases that show how the extension methods work.
public class CheckDigitExtensionShould
{
[Fact]
public void ComputeCheckDigits()
{
Assert.Equal(0, (new List<int> { 0 }).CheckDigit());
Assert.Equal(8, (new List<int> { 1 }).CheckDigit());
Assert.Equal(6, (new List<int> { 2 }).CheckDigit());
Assert.Equal(0, (new List<int> { 3, 6, 1, 5, 5 }).CheckDigit());
Assert.Equal(0, 36155.CheckDigit());
Assert.Equal(8, (new List<int> { 3, 6, 1, 5, 6 }).CheckDigit());
Assert.Equal(8, 36156.CheckDigit());
Assert.Equal(6, 36157.CheckDigit());
Assert.Equal("6", "36157".CheckDigit());
Assert.Equal("3", "7992739871".CheckDigit());
}
[Fact]
public void ValidateCheckDigits()
{
Assert.True((new List<int> { 3, 6, 1, 5, 6, 8 }).HasValidCheckDigit());
Assert.True(361568.HasValidCheckDigit());
Assert.True("361568".HasValidCheckDigit());
Assert.True("79927398713".HasValidCheckDigit());
}
[Fact]
public void AppendCheckDigits()
{
Console.WriteLine("36156".CheckDigit());
Console.WriteLine("36156".AppendCheckDigit());
Assert.Equal("361568", "36156".AppendCheckDigit());
Assert.Equal("79927398713", "7992739871".AppendCheckDigit());
}
}
Compact Luhn check:
public static bool Luhn(string digits)
{
return digits.All(char.IsDigit) && digits.Reverse()
.Select(c => c - 48)
.Select((thisNum, i) => i % 2 == 0
? thisNum
:((thisNum *= 2) > 9 ? thisNum - 9 : thisNum)
).Sum() % 10 == 0;
}
Fiddle: https://dotnetfiddle.net/CCwE48
Here is a correct and fast implementation:
bool PassesLuhnCheck(string value)
{
long sum = 0;
for (int i = 0; i < value.Length; i++)
{
var digit = value[value.Length - 1 - i] - '0';
sum += (i % 2 != 0) ? GetDouble(digit) : digit;
}
return sum % 10 == 0;
int GetDouble(long i)
{
switch (i)
{
case 0: return 0;
case 1: return 2;
case 2: return 4;
case 3: return 6;
case 4: return 8;
case 5: return 1;
case 6: return 3;
case 7: return 5;
case 8: return 7;
case 9: return 9;
default: return 0;
}
}
}
I have tried this code which might help for other future folk:
public string GenerateLuhnNumber(string baseNumber)
{
if (!double.TryParse(baseNumber, out double baseNumberInt))
throw new InvalidWorkflowException($"Field contains non-numeric character(s) : {baseNumber}");
var step2 = string.Empty;
for (var index = baseNumber.Length - 1; index >= 0; index -= 2)
{
var doubleTheValue = (int.Parse(baseNumber[index].ToString())) * 2;
if (doubleTheValue > 9)
doubleTheValue = Math.Abs(doubleTheValue).ToString().Sum(c => Convert.ToInt32(c.ToString()));
step2 = step2.Insert(0, (index != 0 ? baseNumber[index - 1].ToString() : "") + doubleTheValue);
}
var step3 = Math.Abs(Convert.ToDouble(step2)).ToString(CultureInfo.InvariantCulture).Sum(c => Convert.ToDouble(c.ToString())).ToString(CultureInfo.InvariantCulture);
var lastDigitStep3 = Convert.ToInt32(step3[step3.Length - 1].ToString());
string checkDigit = "0";
if (lastDigitStep3 != 0)
checkDigit = (10 - lastDigitStep3).ToString();
return baseNumber + checkDigit;
}
You can do it very simply (reference),
public static bool Mod10Check(string creditCardNumber)
{
// check whether input string is null or empty
if (string.IsNullOrEmpty(creditCardNumber))
{
return false;
}
int sumOfDigits = creditCardNumber.Where((e) => e >= '0' && e <= '9')
.Reverse()
.Select((e, i) => ((int)e - 48) * (i % 2 == 0 ? 1 : 2))
.Sum((e) => e / 10 + e % 10);
return sumOfDigits % 10 == 0;
}
This one will do it I believe:
static void Main(string[] args)
{
string number = "1762483";
int digit = 0;
int sum = 0;
for (int i = 0; i <= number.Length - 1; i++)
{
if (i % 2 == 1)
{
digit = int.Parse(number.Substring(i, 1));
sum += DoubleDigitValue(digit);
Console.WriteLine(digit);
}
else
{
digit = int.Parse(number.Substring(i, 1));
sum += digit;
}
}
Console.WriteLine(sum);
if (sum % 10 == 0)
{
Console.WriteLine("valid");
}
else
{
Console.WriteLine("Invalid");
}
}
static int DoubleDigitValue(int digit)
{
int sum;
int doubledDigit = digit * 2;
if (doubledDigit >= 10)
{
sum = 1 + doubledDigit % 10;
} else
{
sum = doubledDigit;
}
return sum;
}
These are my methods for validating and calculating the last digit. To validate a number simply check that the result of the first method is 0;
private int LuhnChecksum(string input)
{
var length = input.Length;
var even = length % 2;
var sum = 0;
for (var i = length - 1; i >= 0; i--)
{
var d = int.Parse(input[i].ToString());
if (i % 2 == even)
d *= 2;
if (d > 9)
d -= 9;
sum += d;
}
return sum % 10;
}
private int LuhnCalculateLastDigit(string input)
{
var checksum = LuhnChecksum(input + "0");
return checksum == 0 ? 0 : 10 - checksum;
}
I just interprete code from C to C#. Code in C you can find there:(https://uk.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D1%83%D0%BD%D0%B0). I cheked it for a few device.
byte[] data = new byte[19];
//fill the data[]
...
//use it
if (checkByLuhn(data))
{
//check complete
}
...
private bool checkByLuhn(byte[] pPurposed)
{
int nSum = 0;
int nDigits = pPurposed.Length;
int nParity = (nDigits - 1) % 2;
char[] cDigit = new char[] { '0','\0' };
for (int i = nDigits; i > 0; i--)
{
cDigit[0] = (char)pPurposed[i - 1];
int nDigit = (int)Char.GetNumericValue(cDigit[0]);
if (nParity == i % 2)
{
nDigit = nDigit * 2;
}
nSum += nDigit / 10;
nSum += nDigit % 10;
}
return 0 == nSum % 10;
}
Philippe had an excellent answer, but here's a simpler version that is still O(n). I've tested it in xUnit with a dataset of 30 and it is factors faster than some of the upvoted answers.
public static bool CheckLuhnParity(string digits)
{
bool isValid = false;
if (!string.IsNullOrEmpty(digits))
{
long sum = 0;
int parity = digits.Length % 2;
for (int i = 0; i < digits.Length; i++)
{
int digit = digits[^(i + 1)] - '0';
sum += (i % 2 == parity) ? Luhn(digit) : digit;
}
isValid = (sum % 10) == 0;
}
return isValid;
int Luhn(int digit) => (digit *= 2) > 9 ? digit - 9 : digit;
}
This has the same flaw as the accepted answer, though; it doesn't fully implement the Luhn algorithm. It assumes that the actual check digit does not need to be verified which means invalid numbers may be accepted. Here's a better way:
public static bool CheckLuhnDigit(string digits)
{
bool isValid = false;
if (!string.IsNullOrEmpty(digits) && digits.Length > 2)
{
long sum = 0;
for (int i = 0; i < digits.Length - 1; i++)
{
int digit = digits[^(i + 2)] - '0';
sum += (i % 2 == 0) ? Luhn(digit) : digit;
}
int checkDigit = digits[^1] - '0';
isValid = (10 - (sum % 10)) % 10 == checkDigit;
}
return isValid;
int Luhn(int digit) => (digit *= 2) > 9 ? digit - 9 : digit;
}
Does anyone want to attempt O(log n)?
Here's shorter version to get checksum
private int getCheckSum(string number)
{
var sum = number.Reverse() //Reverse
.Select((d, i) => i % 2 == 0 ? Convert.ToInt32(d.ToString()) * 2 : Convert.ToInt32(d.ToString())) //double every 2nd digit including starting
.Select(x => x.ToString().Select(c => Convert.ToInt32(c.ToString())).Sum()) //sum double digit number 18 = 1 + 8 = 9
.Sum(); //Sum all
return (10 - (sum % 10)) % 10;
}
To validate a check sum, pass number without checksum and compare the result with last digit of original number .
Your algorithm is correct, but you're testing it wrong way.
I can see your sample input is from wiki page: Luhn algorithm. Difference is, they are calculating check digit for "7992739871X", where X is the check digit they're looking for. Your code validates number your already have!
Change your input to "79927398713" and it will mark it as correct number.
Update
OK, I see where is the problem. You're not taking this part of algorithm right:
From the rightmost digit, which is the check digit, moving left, double the value of every second digit;
Your code takes every other digit, but not necessary starting from most left digit. Try this code:
for (int i = 0; i < num.Length; i++)
{
d = Convert.ToInt32(num.Substring(num.Length - 1 - i, 1));
if (a % 2 == 0)
d = d * 2;
if (d > 9)
d -= 9;
sum += d;
a++;
}
var checkDigit = 10 - (sum % 10);
I don't know it my nomenclature is correct! Anyway, these are the integer I have, for example :
76
121
9660
And I'd like to round them to the close hundred, such as they must become :
100
100
9700
How can I do it faster in C#? I think about an algorithm, but maybe there are some utilities on C#?
Try the Math.Round method. Here's how:
Math.Round(76d / 100d, 0) * 100;
Math.Round(121d / 100d, 0) * 100;
Math.Round(9660d / 100d, 0) * 100;
I wrote a simple extension method to generalize this kind of rounding a while ago:
public static class MathExtensions
{
public static int Round(this int i, int nearest)
{
if (nearest <= 0 || nearest % 10 != 0)
throw new ArgumentOutOfRangeException("nearest", "Must round to a positive multiple of 10");
return (i + 5 * nearest / 10) / nearest * nearest;
}
}
It leverages integer division to find the closest rounding.
Example use:
int example = 152;
Console.WriteLine(example.Round(100)); // round to the nearest 100
Console.WriteLine(example.Round(10)); // round to the nearest 10
And in your example:
Console.WriteLine(76.Round(100)); // 100
Console.WriteLine(121.Round(100)); // 100
Console.WriteLine(9660.Round(100)); // 9700
Try this expression:
(n + 50) / 100 * 100
Caveat: only works for non-negative n.
Just some addition to #krizzzn's accepted answer...
Do note that the following will return 0:
Math.Round(50d / 100d, 0) * 100;
Consider using the following and make it return 100 instead:
Math.Round(50d / 100d, 0, MidpointRounding.AwayFromZero) * 100;
Depending on what you're doing, using decimals might be a better choice (note the m):
Math.Round(50m / 100m, 0, MidpointRounding.AwayFromZero) * 100m;
I know this is an old thread. I wrote a new method. Hope this will be useful for some one.
public static double Round(this float value, int precision)
{
if (precision < -4 && precision > 15)
throw new ArgumentOutOfRangeException("precision", "Must be and integer between -4 and 15");
if (precision >= 0) return Math.Round(value, precision);
else
{
precision = (int)Math.Pow(10, Math.Abs(precision));
value = value + (5 * precision / 10);
return Math.Round(value - (value % precision), 0);
}
}
Example:
float value = 6666.677777F;
Console.Write(value.Round(2)); //6666.68
Console.Write(value.Round(0)); //6667
Console.Write(value.Round(-2)); //6700
Hi i write this extension this gets the next hundred for each number you pass
/// <summary>
/// this extension gets the next hunfìdred for any number you whant
/// </summary>
/// <param name="i">numeber to rounded</param>
/// <returns>the next hundred number</returns>
/// <remarks>
/// eg.:
/// i = 21 gets 100
/// i = 121 gets 200
/// i = 200 gets 300
/// i = 1211 gets 1300
/// i = -108 gets -200
/// </remarks>
public static int RoundToNextHundred(this int i)
{
return i += (100 * Math.Sign(i) - i % 100);
//use this line below if you want RoundHundred not NEXT
//return i % 100 == byte.MinValue? i : i += (100 * Math.Sign(i) - i % 100);
}
//and for answer at title point use this algoritm
var closeHundred = Math.Round(number / 100D)*100;
//and here the extension method if you prefer
/// <summary>
/// this extension gets the close hundred for any number you whant
/// </summary>
/// <param name="number">number to be rounded</param>
/// <returns>the close hundred number</returns>
/// <remarks>
/// eg.:
/// number = 21 gets 0
/// number = 149 gets 100
/// number = 151 gets 200
/// number = -149 gets -100
/// number = -151 gets -200
/// </remarks>
public static int RoundCloseHundred(this int number)
{
return (int)Math.Round(number / 100D) * 100;
}
If you only want to round integer numbers up (as the OP actually did), then you can resort to this solution:
public static class MathExtensions
{
public static int RoundUpTo(this int number, int nearest)
{
if (nearest < 10 || nearest % 10 != 0)
throw new ArgumentOutOfRangeException(nameof(nearest), $"{nameof(nearest)} must be a positive multiple of 10, but you specified {nearest}.");
int modulo = number % nearest;
return modulo == 0 ? number : modulo > 0 ? number + (nearest - modulo) : number - modulo;
}
}
If you want to perform floating-point (or decimal) rounding, then resort to the answers of #krizzzn and #Jim Aho.
int num = 9660;
int remainder = num % 100;
Console.WriteLine(remainder < 50 ? num - remainder : num + (100 -remainder));
Note: I haven't tested this thoroughly.
I had a similar project internally where the business requirements were to search within the 100's range of a given number and find duplicate DB records. So if the user was using line 856 I would search 800 - 899. If the user was using 8567 I would search 8500 - 8599. Not an exact rounding by 100's, but thought I would include my unique approach as some of these basic coding questions are embedded within a larger business project. To test this I seeded a decimal list from 1 - 99999 and spit the results out into a file.
/// <summary>
/// This method accepts an inbound Line Number and returns the line range
/// in the form of lowest to highest based on 100's
/// Example would be 9122 returns 9100 - 9199
/// It's used for generating some additional BOM Temp functionality.
/// </summary>
/// <param name="inboundNumber"></param>
/// <returns></returns>
public static ProjectLineRange CalculateLineRange(decimal inboundNumber)
{
var lineRange = new ProjectLineRange();
var numberLength = inboundNumber.ToString(CultureInfo.InvariantCulture).Length;
switch (numberLength)
{
case 0: //NULL?
break;
case 1: //Represents 1 - 9
lineRange.LineBottom = 1;
lineRange.LineTop = 99;
break;
case 2: //Represents 10 - 99
lineRange.LineBottom = 1;
lineRange.LineTop = 99;
break;
case 3: //Represents 100 - 999
lineRange = CalculateHundredsRange((int)(inboundNumber / 100));
break;
case 4: //Represents 1000 - 9999
lineRange = CalculateThousandsRange(
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(1, 1)),
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(0, 1)));
break;
case 5: //Represents 10000 - 99999
lineRange = CalculateTenThousandsRange(
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(2, 1)),
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(1, 1)),
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(0, 1)));
break;
}
return lineRange;
}
public class ProjectLineRange
{
public decimal LineBottom { get; set; }
public decimal LineTop { get; set; }
}
/// <summary>
/// Helper method to return the range for the 100's place
/// </summary>
/// <param name="hundredsPlaceValue"></param>
/// <returns></returns>
public static ProjectLineRange CalculateHundredsRange(int hundredsPlaceValue)
{
var tempLineRange = new ProjectLineRange();
tempLineRange.LineBottom = hundredsPlaceValue * 100;
tempLineRange.LineTop = tempLineRange.LineBottom + 99;
return tempLineRange;
}
/// <summary>
/// Helper method to return the range for the 100's place when factoring a 1000's number
/// </summary>
/// <param name="hundredsPlaceValue"></param>
/// <param name="thousandsPlaceValue"></param>
/// <returns></returns>
public static ProjectLineRange CalculateThousandsRange(int hundredsPlaceValue, int thousandsPlaceValue)
{
var tempLineRange = new ProjectLineRange();
var tempThousands = thousandsPlaceValue * 1000;
var hundredsRange = CalculateHundredsRange(hundredsPlaceValue);
tempLineRange.LineBottom = tempThousands + hundredsRange.LineBottom;
tempLineRange.LineTop = tempThousands + hundredsRange.LineTop;
return tempLineRange;
}
/// <summary>
/// Helper method to return the range for the 100's place when factoring a 10000's number
/// </summary>
/// <param name="hundredsPlaceValue"></param>
/// <param name="thousandsPlaceValue"></param>
/// <param name="tenThousandsPlaceValue"></param>
/// <returns></returns>
public static ProjectLineRange CalculateTenThousandsRange(int hundredsPlaceValue, int thousandsPlaceValue, int tenThousandsPlaceValue)
{
var tempLineRange = new ProjectLineRange();
var tempThousands = thousandsPlaceValue * 1000;
var tempTenThousands = tenThousandsPlaceValue * 10000;
var hundredsRange = CalculateHundredsRange(hundredsPlaceValue);
tempLineRange.LineBottom = tempTenThousands + tempThousands + hundredsRange.LineBottom;
tempLineRange.LineTop = tempTenThousands + tempThousands + hundredsRange.LineTop;
return tempLineRange;
}
public static class Maths
{
public static int Round(this int value, int precision)
{
var coef = Math.Pow(10, Math.Abs(precision));
var x = (int)Math.Round(value / coef, 0);
return x * (int)coef;
}
}
var number = 34569;
Debug.WriteLine(number.Round(0));//34569
Debug.WriteLine(number.Round(1));//34570
Debug.WriteLine(number.Round(2));//34600
Debug.WriteLine(number.Round(3));//35000
Debug.WriteLine(number.Round(4));//30000
Debug.WriteLine(number.Round(5));// 0
Debug.WriteLine(number.Round(6));// 0
I am wanting to generate a random array of sequences that repeat and only use each number once. For example, given a range of 0-9 with 2 different seeds you might get
Seed 1: 7 3 5 9 0 8 1 2 6 4 | 7 3 5 9 0 8 1 2 6 4 | 7 3 5 9 0 8 1 2 6 4
Seed 2: 2 5 7 1 4 9 6 8 3 0 | 2 5 7 1 4 9 6 8 3 0 | 2 5 7 1 4 9 6 8 3 0
From what I understand, a Linear Congruential Random Number Generator or LCRNG or LCG can give me this http://en.wikipedia.org/wiki/Linear_congruential_generator
Any idea if an implementation exists in C# or how I would get started with writing one.
How does a Mersenne Twister differ from an LCG?
Not sure all of my questions are answered, but here is what I ended up using. Because I am bounding the sample size to the range of values from max to min, I am selecting a different prime number that stays static as long as the same initial seed is given. I do this because I want the same sequence given the same seed and the same min/max bounds for repeatability of testing.
Please critique anything I do here, this is just what I came up with in a jiffy:
using System;
using System.Collections.Generic;
namespace FULLCYCLE
{
public class RandomNumber
{
private int _value;
private int _prime;
private static List<int> primes = new List<int>()
{
11,
23,
47,
97,
797,
1597,
6421,
25717,
51437,
102877,
411527,
823117,
1646237,
3292489,
6584983,
13169977,
26339969,
52679969,
105359939,
210719881,
421439783,
842879579,
1685759167
};
public RandomNumber( int seed )
{
_prime = primes[seed%primes.Count];
_value = seed;
}
public int Next( int min, int max )
{
int maxrate = (max-min+1);
if (_value > maxrate)
{
_value = _value % maxrate;
}
_value = (_value + _prime) % maxrate;
return _value + min;
}
}
}
Why not just use the existing Random class and a Knuth shuffle on your input sequence?
Regarding your edit, there are several problems with your LCG as a random number generator...
It can produce obvious patterns:
// generates 3, 4, 5, 6, 7, 8, 9, 0, 1, 2
var rng = new RandomNumber(42);
for (int i = 0; i < 10; i++) Console.WriteLine(rng.Next(0, 9));
It can repeat itself:
// generates 579, 579, 579, 579, 579, 579, 579, 579, 579, 579
var rng = new RandomNumber(123);
for (int i = 0; i < 10; i++) Console.WriteLine(rng.Next(456, 51892));
There are many other seed/min/max combinations that will generate problematic results.
Try the following code:
namespace System
{
/// <summary>
/// Represents a pseudo-random number generator using the linear congruential method:
/// X[i+1] = (a • X[i] + c) % m (where i is greater than or equal to 0).
/// </summary>
public class LinearCongruentialRandom : Random
{
private int _x = 1971111612;
private int _a = 2147483629;
private int _c = 2147483587;
private int _m = 2147483647;
/// <summary>
/// Initializes a new instance of <see cref="LinearCongruentialRandom"/> with default values.
/// </summary>
public LinearCongruentialRandom()
{
= base.Next(0, _m);
}
/// <summary>
/// Initializes a new instance of <see cref="LinearCongruentialRandom"/> with default values.
/// </summary>
public LinearCongruentialRandom(int seed)
{
if (seed >= _m) throw new ArgumentOutOfRangeException(nameof(seed), seed, null);
_x = seed;
}
/// <summary>
/// Initializes a new instance of <see cref="LinearCongruentialRandom"/> with the specified parameters.
/// </summary>
/// <param name="seed">Initial seed value less than m.</param>
/// <param name="a">A multiple of p for every prime p that is a divisor of m.</param>
/// <param name="c">Increment c. The numbers c and m must be relatively prime.</param>
/// <param name="m">The length of the repetition period m. The numbers c and m must be relatively prime.</param>
public LinearCongruentialRandom(int seed, int a, int c, int m) : this(seed)
{
_a = a;
_c=c;
_m=m;
}
/// <inheritdoc cref="Random.Next()"/>
public override int Next()
{
return _x = (_a * _x + _c) % _m;
}
/// <inheritdoc cref="Random.NextBytes(byte[])"/>
public override void NextBytes(byte[] buffer)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer));
unchecked
{
for (int index = 0; index < buffer.Length; ++index)
buffer[index] = (byte)Next();
}
}
}
}