Get values from an array - c#

This code get a user to enter 5 numbers, stores the in an array, and works out the average
double average;
double variance;
int i;
int[] arr = new int[5]; // 5 size array
for (i = 0; i < 5; i++)
{
Console.Write("\n Enter your number:\t");
arr[i] = Convert.ToInt32(Console.ReadLine());
}
Console.WriteLine("\n");
average = arr.Sum() / 5.0;
Console.WriteLine("\n The average is {0}", average);
Console.ReadLine();
I am trying to work out the variance which is (number – average) * (number – average).
However I am unsure on how to pull out each number from the array and perform this calculation?
Any help much appreciated thanks

You can get the standard deviation as follows:
double average = arr.Average();
double sumOfSquaresOfDifferences = arr.Select(val => (val - average) * (val - average)).Sum();
double sd = Math.Sqrt(sumOfSquaresOfDifferences / arr.Length);

Your Question
Make an Extension Method.. not Tested but it should work if what is described here is correct
static class MathsExtensions
{
public static double GetVariance(this double[] values)
{
var avg = values.Average();
return values.Select(value => (value - avg) * (value - avg)).Sum() / values.Count();
}
}
Just gave it a little test.
double[] arr = { 8, 7, 9, 10, 6 };
Console.WriteLine(arr.GetVariance());
Console.ReadLine();
It returns 2 which - according to my link - is correct.
This might be helpful in the feauture
If you next Time have a similar Problem, you should propably just google like "how do i calculate variance" and then create your algorithm based on the theory. But alaways look up if there does already exist a solution

Related

Sum range using loop, calculate sum of odd and even numbers

Hi I am sick of searching I could not find the exact code for my question.
I need to code the sum of the odd numbers from 1 to 100
and sum of the even numbers from 2 to 100.
This is what i have so far.
Thank you so much
// 1) using for statement to Sum Up a Range of values using Interactive
Console.WriteLine(" Sum Up a Range of values entered by User ");
Console.WriteLine();
// 2) Declare the Variables to be used in the Project
string strFromNumber, strToNumber;
int fromNumber, toNumber;
int sum = 0;
int i, even = 0, odd = 0;
int[] array = new int[10];
// 3) Prompt the User to Enter the From Number to Sum From
Console.Write("Enter the From Number to Sum From: ");
strFromNumber = Console.ReadLine();
fromNumber = Convert.ToInt32(strFromNumber);
// 4) Prompt the User to Enter the To Number to Sum To
Console.Write("Enter the To Number to Sum To: ");
strToNumber = Console.ReadLine();
toNumber = Convert.ToInt32(strToNumber);
// 5) Use for statement to Sum up the Range of Numbers
for (i = fromNumber; i <= toNumber; ++i)
{
sum += i;
}
if //(array[i] % 2 == 0) //here if condition to check number
{ // is divided by 2 or not
even = even + array[i]; //here sum of even numbers will be stored in even
}
else
{
odd = odd + array[i]; //here sum of odd numbers will be stored in odd.
}
Console.WriteLine("The Sum of Values from {0} till {1} = {2}",
fromNumber, toNumber, sum);
Console.ReadLine();
There is no need to write the complex code which you have written.
Problem is to calculate the sum of arithmetic progression. The formula to find the sum of an arithmetic progression is Sn = n/2[2a + (n − 1) × d] where, a = first term of arithmetic progression, n = number of terms in the arithmetic progression and d = common difference.
So in case of odd numbers its a = 1, n = 50 and d = 2
and in case of even numbers its a = 2, n = 50 and d = 2
and if you try to normalize these above formulas, it will be more easy based on your problem.
the sum of the first n odd numbers is Sn= n^2
the sum of the first n even numbers is n(n+1).
and obviously, it's very simple to loop from ( 1 to 99 with an increment of 2 ) and ( 2 to 100 with an increment of 2 )
In the simplest case, you can try looping in fromNumber .. toNumber range while adding
number either to even or to odd sum:
// long : since sum of int's can be large (beyond int.MaxValue) let's use long
long evenSum = 0;
long oddSum = 0;
for (int number = fromNumber; number <= toNumber; ++number) {
if (number % 2 == 0)
evenSum += number;
else
oddSum += number;
}
Console.WriteLine($"The Sum of Values from {fromNumber} till {toNumber}");
Console.WriteLine($"is {evenSum + oddSum}: {evenSum} (even) + {oddSum} (odd).");
Note, that you can compute both sums in one go with a help of arithmetics progression:
private static (long even, long odd) ComputeSums(long from, long to) {
if (to < from)
return (0, 0); // Or throw ArgumentOutOfRangeException
long total = (to + from) * (to - from + 1) / 2;
from = from / 2 * 2 + 1;
to = (to + 1) / 2 * 2 - 1;
long odd = (to + from) / 2 * ((to - from) / 2 + 1);
return (total - odd, odd);
}
Then
(long evenSum, long oddSum) = ComputeSums(fromNumber, toNumber);
Console.WriteLine($"The Sum of Values from {fromNumber} till {toNumber}");
Console.WriteLine($"is {evenSum + oddSum}: {evenSum} (even) + {oddSum} (odd).");
From the code snippet you shared, it seems like the user gives the range on which the sum is calculated. Adding to #vivek-nuna's answer,
Let's say the sum of the first N odd numbers is given by, f(n) = n^2 and
the sum of the first N even numbers is given by, g(n) = n(n + 1).
So the sum of odd numbers from (l, r) = f(r) - f(l - 1).
Similarly, the sum of even numbers from (l, r) = g(r) - g(l - 1).
Hope this helps.

Random() times 2^32 - 1 always returns even last digit

I have encountered this weird behaviour, which is probably best described by a small example:
Random R = new Random();
for (int i = 0; i < 10_000; i++)
{
double d = R.NextDouble() * uint.MaxValue;
}
Now, the last digit of d before the decimal mark is always even, i.e. int r = (int) (d % 10) is always 0, 2, 4, 6, or 8. There are odd digits on either side, though.
I suspected that multiplying with uint.MaxValue (2^32 - 1) could force some rounding error in the last digits, but since double has more than 50 bits of precision, this should beat uint with about 20 bits to spare after the separator. This behaviour also occurs if I explicitly store uint.MaxValue as a double before the multiplication and use that instead.
Can someone shed any light on this?
This is a deficiency in the .Net Random class.
If you inspect the source code you will see the following comment in the implementation of the private method GetSampleForLargeRange():
// The distribution of double value returned by Sample
// is not distributed well enough for a large range.
// If we use Sample for a range [Int32.MinValue..Int32.MaxValue)
// We will end up getting even numbers only.
This is used in the implementation of Next():
public virtual int Next(int minValue, int maxValue) {
if (minValue>maxValue) {
throw new ArgumentOutOfRangeException("minValue",Environment.GetResourceString("Argument_MinMaxValue", "minValue", "maxValue"));
}
Contract.EndContractBlock();
long range = (long)maxValue-minValue;
if( range <= (long)Int32.MaxValue) {
return ((int)(Sample() * range) + minValue);
}
else {
return (int)((long)(GetSampleForLargeRange() * range) + minValue);
}
}
But it is NOT used for the values returned from NextDouble() (which just returns the value returned from Sample().
So the answer is that NextDouble() is not well-distributed.
You can use RNGCryptoServiceProvider to generate better random numbers, but it's a bit of a fiddle to create the double. From this answer:
static void Main()
{
var R = new RNGCryptoServiceProvider();
var bytes = new Byte[8];
for (int i = 0; i < 10_000; i++)
{
R.GetBytes(bytes);
var ul = BitConverter.ToUInt64(bytes, 0) / (1 << 11);
var d = ul / (double)(1UL << 53);
d *= uint.MaxValue;
Console.WriteLine(d);
}
}

Pairs of amicable numbers

I have a task to find pairs of amicable numbers and I've already solved it. My solution is not efficient, so please help me to make my algorithm faster.
Amicable numbers are two different numbers so related that the sum of the proper divisors of each is equal to the other number. The smallest pair of amicable numbers is (220, 284). They are amicable because the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110, of which the sum is 284; and the proper divisors of 284 are 1, 2, 4, 71 and 142, of which the sum is 220.
Task: two long numbers and find the first amicable numbers between them. Let s(n) be the sum of the proper divisors of n:
For example:
s(10) = 1 + 2 + 5 = 8
s(11) = 1
s(12) = 1 + 2 + 3 + 4 + 6 = 16
If s(firstlong) == s(secondLong) they are amicable numbers
My code:
public static IEnumerable<long> Ranger(long length) {
for (long i = 1; i <= length; i++) {
yield return i;
}
}
public static IEnumerable<long> GetDivisors(long num) {
return from a in Ranger(num/2)
where num % a == 0
select a;
}
public static string FindAmicable(long start, long limit) {
long numberN = 0;
long numberM = 0;
for (long n = start; n <= limit; n++) {
long sumN = GetDivisors(n).Sum();
long m = sumN;
long sumM = GetDivisors(m).Sum();
if (n == sumM ) {
numberN = n;
numberM = m;
break;
}
}
return $"First amicable numbers: {numberN} and {numberM}";
}
I generally don't write C#, so rather than stumble through some incoherent C# spaghetti, I'll describe an improvement in C#-madeup-psuedo-code.
The problem seems to be in your GetDivisors function. This is linear O(n) time with respect to each divisor n, when it could be O(sqrt(n)). The trick is to only divide up to the square root, and infer the rest of the factors from that.
GetDivisors(num) {
// same as before, but up to sqrt(num), plus a bit for floating point error
yield return a in Ranger((long)sqrt(num + 0.5)) where num % a == 0
if ((long)sqrt(num + 0.5) ** 2 == num) { // perfect square, exists
num -= 1 // don't count it twice
}
// repeat, but return the "other half"- num / a instead of a
yield return num/a in Ranger((long)sqrt(num + 0.5)) where num % a == 0
}
This will reduce your complexity of that portion from O(n) to O(sqrt(n)), which should provide a noticeable speedup.
There is a simple formula giving the sum of divisors of a number knowing its prime decomposition:
let x = p1^a1 * ... * pn^an, where pi is a prime for all i
sum of divisors = (1+p1+...+p1^a1) * ... (1+pn+...+pn^an)
= (1-p1^(a1+1))/(1-p1) * ... ((1-pn^(an+1))/(1-pn)
In order to do a prime decomposition you must compute all prime numbers up to the square root of the maximal value in your search range. This is easily done using the sieve of Erathostenes.

Counting how many numbers in an array are between 1.5 - 35 C#

I am trying to work out how to count how many numbers in an array fall between the values of, 1.5 - 35. I am struggling to work out which method I should use to achieve this. I was thinking maybe a for-each embedded loop but then the more I think about it the more I question that method. Any help would be appreciated on how I may achieve this, I will post my current code below as I have already worked out how to calculate the average and minimum price for the equation.
class Program
{
static void Main(string[] args)
{
read_stock_price();
}
static void read_stock_price()
{
Console.Write("Enter how many stocks to enter price for: ");
int numStocks = Convert.ToInt32(Console.ReadLine());
double[] arrayinput = new double[numStocks];
for (int i = 0; i < numStocks; ++i)
{
Console.Write("Enter price for stock number: ");
arrayinput[i] = Convert.ToDouble(Console.ReadLine());
}
double sum = arrayinput.Sum();
double average = sum / numStocks;
Console.WriteLine("Average price: {0} out of {1} stocks", average, numStocks);
Console.WriteLine("Minimum price: {0}", arrayinput.Min());
}
}
You can use LINQ instead of a for-each. First filter the array then count the elements.
var count = arrayinput
.Where(x => 1.5 <= x && x <= 35.0)
.Count();
Shortest way is Enumerable.Count
var count = arrayinput.Count(x => 1.5 < x && x < 35.0);
if we assumed arrayinput is your filled array you can use this:
double[] arrayinput = new double[numStocks];
double[] filteredArray = arrayinput.Where(p => p > 1.5 && p < 3.5).ToArray();
int count = filteredArray.Count();
this code filter your array with value between 1.5 & 3.5.

algorithm to find the correct set of numbers

i will take either python of c# solution
i have about 200 numbers:
19.16
98.48
20.65
122.08
26.16
125.83
473.33
125.92
3,981.21
16.81
100.00
43.58
54.19
19.83
3,850.97
20.83
20.83
86.81
37.71
36.33
6,619.42
264.53
...
...
i know that in this set of numbers, there is a combination of numbers that will add up to a certain number let's say it is 2341.42
how do i find out which combination of numbers will add up to that?
i am helping someone in accounting track down the correct numbers
Here's a recursive function in Python that will find ALL solutions of any size with only two arguments (that you need to specify).
def find_all_sum_subsets(target_sum, numbers, offset=0):
solutions = []
for i in xrange(offset, len(numbers)):
value = numbers[i]
if target_sum == value:
solutions.append([value])
elif target_sum > value:
sub_solutions = find_all_sum_subsets(target_sum - value, numbers, i + 1)
for sub_solution in sub_solutions:
solutions.append(sub_solution + [value])
return solutions
Here it is working:
>>> find_all_sum_subsets(10, [1,2,3,4,5,6,7,8,9,10,11,12])
[[4, 3, 2, 1], [7, 2, 1], [6, 3, 1], [5, 4, 1], [9, 1], [5, 3, 2], [8, 2], [7, 3], [6, 4], [10]]
>>>
You can use backtracking to generate all the possible solutions. This way you can quickly write your solution.
EDIT:
You just implement the algoritm in C#:
public void backtrack (double sum, String solution, ArrayList numbers, int depth, double targetValue, int j)
{
for (int i = j; i < numbers.Count; i++)
{
double potentialSolution = Convert.ToDouble(arrayList[i] + "");
if (sum + potentialSolution > targetValue)
continue;
else if (sum + potentialSolution == targetValue)
{
if (depth == 0)
{
solution = potentialSolution + "";
/*Store solution*/
}
else
{
solution += "," + potentialSolution;
/*Store solution*/
}
}
else
{
if (depth == 0)
{
solution = potentialSolution + "";
}
else
{
solution += "," + potentialSolution;
}
backtrack (sum + potentialSolution, solution, numbers, depth + 1, targetValue, i + 1);
}
}
}
You will call this function this way:
backtrack (0, "", numbers, 0, 2341.42, 0);
The source code was implemented on the fly to answer your question and was not tested, but esencially you can understand what I mean from this code.
[Begin Edit]:
I misread the original question. I thought that it said that there is some combination of 4 numbers in the list of 200+ numbers that add up to some other number. That is not what was asked, so my answer does not really help much.
[End Edit]
This is pretty clunky, but it should work if all you need is to find the 4 numbers that add up to a certain value (it could find more than 4 tuples):
Just get your 200 numbers into an array (or list or some IEnumerable structure) and then you can use the code that I posted. If you have the numbers on paper, you will have to enter them into the array manually as below. If you have them in softcopy, you can cut and paste them and then add the numbers[x] = xxx code around them. Or, you could cut and paste them into a file and then read the file from disk into an array.
double [] numbers = new numbers[200];
numbers[0] = 123;
numbers[1] = 456;
//
// and so on.
//
var n0 = numbers;
var n1 = numbers.Skip(1);
var n2 = numbers.Skip(2);
var n3 = numbers.Skip(3);
var x = from a in n0
from b in n1
from c in n2
from d in n3
where a + b + c + d == 2341.42
select new { a1 = a, b1 = b, c1 = c, d1 = d };
foreach (var aa in x)
{
Console.WriteLine("{0}, {1}, {2}, {3}", aa.a1, aa.b1, aa.c1, aa.d1 );
}
Try the following approach if finding a combination of any two (2) numbers:
float targetSum = 3;
float[] numbers = new float[]{1, 2, 3, 4, 5, 6};
Sort(numbers); // Sort numbers in ascending order.
int startIndex = 0;
int endIndex = numbers.Length - 1;
while (startIndex != endIndex)
{
float firstNumber = numbers[startIndex];
float secondNumber = numbers[endIndex];
float sum = firstNumber + secondNumber;
if (sum == targetSum)
{
// Found a combination.
break;
}
else if (sum < targetSum)
{
startIndex++;
}
else
{
endIndex--;
}
}
Remember that when use floating-point or decimal numbers, rounding could be an issue.
This should be implemented as a recursive algorithm. Basically, for any given number, determine if there is a subset of the remaining numbers for which the sum is your desired value.
Iterate across the list of numbers; for each entry, subtract that from your total, and determine if there is a subset of the remaining list which sums up to the new total. If not, try with your original total and the next number in the list (and a smaller sublist, of course).
As to implementation:
You want to define a method which takes a target number, and a list, and which returns a list of numbers which sum up to that target number. That algorithm should iterate through the list; if an element of the list subtracted from the target number is zero, return that element in a list; otherwise, recurse on the method with the remainder of the list, and the new target number. If any recursion returns a non-null result, return that; otherwise, return null.
ArrayList<decimal> FindSumSubset(decimal sum, ArrayList<decimal> list)
{
for (int i = 0; i < list.Length; i++)
{
decimal value = list[i];
if (sum - value == 0.0m)
{
return new ArrayList<decimal>().Add(value);
}
else
{
var subset = FindSumSubset(sum - value, list.GetRange(i + 1, list.Length -i);
if (subset != null)
{
return subset.Add(value);
}
}
}
return null;
}
Note, however, that the order of this is pretty ugly, and for significantly larger sets of numbers, this becomes intractable relatively quickly. This should be doable in less than geologic time for 200 decimals, though.

Categories