Why do different algorithms of summing not match? - c#

Assume that I want to get sum of all squares from M to N. I googled a bit and found this formula:
(1^2 + 2^2 + 3^2 + ... + N^2) = (N * (N + 1) * (2N + 1)) / 6
so I write this code:
static void Main(string[] args)
{
const int from = 10;
const int to = 50000;
Console.WriteLine(SumSquares(from, to));
Console.WriteLine(SumSquares2(from, to));
}
static long SumSquares(int m, int n)
{
checked
{
long x = m - 1;
long y = n;
return (((y*(y + 1)*(2*y + 1)) - (x*(x + 1)*(2*x + 1)))/6);
}
}
static long SumSquares2(int m, int n)
{
long sum = 0;
for (int i = m; i <= n; ++i)
{
sum += i * i;
}
return sum;
}
it works fine until 40k, but when N becomes 50k it fails. Output for 50k:
41667916674715
25948336371355
Press any key to continue . . .
I think it's an overflow or something, so I added checked keyword and tried to change long to double, but I got the same result. How can it be explained? How to get correct result without loops?

Your second method is overflowing because you are using an int in the loop. Change it to a long as follows (and also add checked):
static long SumSquares2(int m, int n)
{
checked
{
long sum = 0;
for (long i = m; i <= n; ++i)
{
sum += i*i;
}
return sum;
}
}
What was going wrong is that i*i was being calculated internally as an int data type even though the result was being cast to a long data type (i.e. the variable sum), and so it overflowed.

While you are using long for the result, you are still using int for the operators. I would define M and N as long or even BigInteger, and the same for the result. If you do not, you are probably doing int arithmetic still, even though your result is of type long.
I tried your code, and got the results you got. But then I changed every int to long and got the two numbers to match, up to an N of 1600000.
Using BigInteger, I am up to 160000000 and still working ok (result for m=10 and n=160000000 is 13653333461333333359999715, both ways).
To use BigInteger, you will need to add a reference to the System.Numerics dll to your project, and you will need to have a statement at the top of your code including that library.
using System.Numerics;
namespace ConsoleFiddle
{
class Program
{
static void Main(string[] args)
{
BigInteger from = 10;
BigInteger to = 160000000;
Console.WriteLine(SumSquares(from, to));
Console.WriteLine(SumSquares2(from, to));
Console.ReadKey();
}
static BigInteger SumSquares(BigInteger m, BigInteger n)
{
checked
{
BigInteger x = m - 1;
BigInteger y = n;
return (((y * (y + 1) * (2 * y + 1)) - (x * (x + 1) * (2 * x + 1))) / 6);
}
}
static BigInteger SumSquares2(BigInteger m, BigInteger n)
{
checked
{
BigInteger sum = 0;
for (BigInteger i = m; i <= n; ++i)
{
sum += i * i;
}
return sum;
}
}
For an M of 4000000000000000000 (4 x 10^18), and an N of 4000000000100000000. This code still works and gives an immediate result with the first method (1600000016040000000400333333338333333350000000). With the second method it takes it a little while (100 million loop iterations) but gives the same result.

Most probably you are experiencing integer overflow, as the range of long is limited. Probably you have disabled exceptions for integer overflow, so no exception is thrown. The exceptions for integer overflow can be disabled and enabled in the project properties in Visual Studio, if I'm not mistaken.

Related

I need exact value but my integer variable overflows

I need to do divide the number which equals to sum of some big values. But after a while, it overflows and it equals to a negative number. I tried to use BigInteger,decimal and double but it doesn't work again.
Error message:System.ArgumentException 'Value of '256' is not valid for 'red'. 'red' should be greater than or equal to 0 and less than or equal to 255.'
Edit: When i checked value of GaussFiltresi[syc] i have seen that :'GaussFiltresi[syc]' threw an exception of type 'System.IndexOutOfRangeException'
#region Gaussian Filter
public void gaussianfilter (int SablonBoyutu,Bitmap GirisResmi,Bitmap CikisResmi)
{
int ResimGenisligi = GirisResmi.Width;
int ResimYuksekligi = GirisResmi.Height;
int syc = 0;
BigInteger toplamR;
BigInteger filtrekatsayitoplami;
BigInteger ortalamaR;
int kernelsinir = ((SablonBoyutu - 1) / 2);
for ( i = -kernelsinir; i <= kernelsinir; i++)
{
for ( j = -kernelsinir; j <= kernelsinir; j++)
{
//some calculations
}
}
for (int x = (kernelsinir); x < ResimGenisligi - kernelsinir; x++)
{
for (int z = (kernelsinir); z < ResimGenisligi - kernelsinir; z++)
{
syc = 0;
toplamR = 0;
for (int y = -(kernelsinir); y <= kernelsinir; y++)
{
for (int d = -(kernelsinir); d <= kernelsinir; d++)
{
OkunanRenk = GirisResmi.GetPixel(x + y, d + z);
toplamR += GaussFiltresi[syc] * (BigInteger)(OkunanRenk.R);
//toplam R=1662424090 and GaussFiltresi[syc] = 5389698 before overflowing
syc++;
}
}
ortalamaR = toplamR / filtrekatsayitoplami; //toplamR is negative
CikisResmi.SetPixel(x, z, Color.FromArgb((int)ortalamaR, (int)ortalamaR,(int)ortalamaR));
}
}
}
#endregion
With a reference to System.Numerics.dll, you can use BigInteger instead of Int64 (a.k.a. long).
Another option is to use double that does not overflow (to PositiveInfinity) before 10**308, or 1e+308. Or decimal that goes to more than 1e+28m.
Update after comments: Your expression:
GaussFiltresi[syc] * OkunanRenk.R
is an int times an int. In fact becomes 14650719 * 160, which gives -1950852256. To have the two operands promoted to BigInteger, such that the multiplication * will be multiplication of big-ints (that never overflow), cast either operand to BigInteger (the other will be promoted to BigInteger for free), just as I said in my comment:
GaussFiltresi[syc] * (BigInteger)(OkunanRenk.R)
so the entire statement becomes:
toplamR += GaussFiltresi[syc] * (BigInteger)(OkunanRenk.R);
A multiplication of an int by an int will be done as an int multiplication (and the result may "wrap around"). It is not changed by the fact that the result is going to be +=-ed to a BigInteger later. That was the reason why it did not work after your initial code changes.

c# need to find the sum of all ints from a loop

I'm kinda new to c# and I'm doing some projects on my own. In this project I need to find the values of the arithmetic a + (a + b) + (a + 2b) and so on. Then I need to add all the answers together. I have the first part done but I'm unsure how to add all the values I get from the loop.
class Program
{
static void Main(string[] args)
{
int a = 22;
int b = 8;
int answer;
Console.WriteLine(a);
for (int i = 1; i <= 43; i++)
{
answer = a + b * i;
Console.WriteLine(answer);
}
}
}
You need to accumulate the answer is some way. You can do that be defining another variable to hold the summation. If the loop is many iterations you may have to worry about overflow.
int total;
for (int i = 1; i <= 43; i++)
{
answer = a + b * i;
total += answer;
Console.WriteLine(answer);
}
Start with i=0
Use += operator for answer.
Consider Sum extension method from System.Linq
Using Linq you can use the Enumerable.Range() method to get a list of integers, then you can sum them.
var total = Enumerable.Range(1, 43).Sum();

Evaluating Knuth's arrow notation in a function

I am having trouble calculating Knuth's arrow notation, which is ↑ and can be found here, within a function. What I've made so far is:
int arrowCount = (int)arrowNum.Value; // Part of
BigInteger a = (int)aNum.Value; // the input I
BigInteger b = (int)bNum.Value; // already have
BigInteger result = a;
BigInteger temp = a;
for(int i = 0; i < arrowCount; i++)
{
result = Power(temp, b);
temp = r;
b = a;
}
with power being
BigInteger Power(BigInteger Base, BigInteger Pow)
{
BigInteger x = Base;
for(int i = 0; i < (Pow-1); i++)
{
x *= Base;
}
return x;
}
but it's incorrect with it's values and I can't figure out a way to fix it. It can handle 1 arrow problems like 3↑3 (which is 3^3 = 9), but it can't handle any more arrows than that.
I need a way to figure out more arrows, such as 3↑↑3,
which should be 7625597484987 (3^27) and I get 19683 (27^3). If you could help me to figure how I could get the proper output and explain what it is I'm doing wrong, I would greatly appreciate it.
I wrote it in java, and use double for input parameter:
private static double knuthArrowMath(double a, double b, int arrowNum)
{
if( arrowNum == 1)
return Math.pow(a, b);
double result = a;
for (int i = 0; i < b - 1; i++)
{
result = knuthArrowMath(a, result, arrowNum - 1);
}
return result;
}
If you expect 7625597484987 (3^27) but get 19683 (27^3), isn't it then a simple matter of swapping the arguments when calling your power function?
Looking at your Power function your code snippet seems to call Power with temp as base and b as power:
int arrowCount = (int)arrowNum.Value; // Part of
BigInteger a = (int)aNum.Value; // the input I
BigInteger b = (int)bNum.Value; // already have
BigInteger result = a;
BigInteger temp = a;
for(int i = 0; i < arrowCount; i++)
{
result = Power(temp, b);
temp = result;
b = a;
}
Shouldn't temp an b be swapped so you get result = Power(b, temp) to get the desired result?
So pass 1 results calls Power(3, 3) resulting in temp = 27 and pass 2 calls Power(3, 27). The reason it only works for single arrow now is because swapping arguments for the first Power(base, power) call doesn't matter.
As you point out in your answer this doesn't cover all situations. Given the examples you provided I created this little console application:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Arrow(3, 3));
Console.WriteLine(Arrow(4, 4, 1));
Console.WriteLine(Arrow(3, 4, 1));
Console.ReadKey();
}
private static BigInteger Arrow(BigInteger baseNumber, BigInteger arrows)
{
return Arrow(baseNumber, baseNumber, arrows-1);
}
private static int Arrow(BigInteger baseNumber, BigInteger currentPower, BigInteger arrows)
{
Console.WriteLine("{0}^{1}", baseNumber, currentPower);
var result = Power(baseNumber, currentPower);
if (arrows == 1)
{
return result;
}
else
{
return Arrow(baseNumber, result, arrows - 1);
}
}
private static BigInteger Power(BigInteger number, BigInteger power)
{
int x = number;
for (int i = 0; i < (power - 1); i++)
{
x *= number;
}
return x;
}
}
I came up with a way to use the BigInteger.Pow() function.
It might look a little odd, but that is because the C# BigInterger.Pow(x, y) only accepts an int for y, and teterations have HUGE exponents. I had to "flip the script" and convert x^y = y^x for this specific case.
I didn't add in any error checking, and it expects all numbers to be positive ints.
I know this works for x^^2 and x^^3. I also know it works for 2^^4 and 2^^5. I don't have the computing power/memory/math knowledge to know if it works for any other numbers. 2^^4 and 2^^5 were the only ones I could check and test. It may work for other numbers but I was not able to confirm that.
int baseNum = 4;
int exp = 3;
// this example is 4^^3
BigInteger bigAnswer = tetration(baseNum, exp);
// Here is what the method that "does the work" looks like.
// This looks a little odd but that is because I am using BigInteger.Pow(x,y)
// Unfortunately, y can only be an int. Tetrations have huge exponents, so I had to figure out a
// way to have x^y work as y^x for this specific application
// no error checking in here, and it expects positive ints only
// I *know* this works for x^^2, x^^3, but I don't know if it works for
// any other number than 2 at ^^4 or higher
public static BigInteger tetration(int baseNum, int exp)
{
if (exp > 2)
{
exp = (int)Math.Pow(baseNum, (exp - 3));
}
else
{
exp = exp - 2;
}
Func<BigInteger, int, BigInteger> bigPowHelper = (x, y) => BigInteger.Pow(x, y);
BigInteger bigAnswer = baseNum;
for (int i = 0; i < Math.Pow(baseNum, exp); i++)
{
bigAnswer = bigPowHelper(bigAnswer, baseNum);
}
return bigAnswer;
}

Trouble implementing recursive method for mean of an array

I have an array of numbers(double) and I want to implement a recursive method in C# to calculate a running average for a given position in the array using the following algorithm:
µn+1 = (n * µn)/(n+1) + Xn+1/n
where µn+1 is the average at the position I'm interested in,
µn is the average of the prior iteration and Xn+1 is the nth element of the array.
I have been able to do it with an averaging function and an iterative function but not recursion:
static double Flow(double[] A, int n)
{
double U = (A[0] + A[1]) / 2.0;
if (n == 2) { return U; }
else if (n == 1) { return A[0]; }
else
{
for (int i = 3; i <= n; i++)
{
U = Avg(A, U, i);
}
}
return U;
}
static double Avg(double[] A, double M, int n)
{
double a =(n - 1) * M / (n);
double b = A[n - 1] / (n);
return a + b;
}
You need to define µ1, whatever your initial value of the first average is, for your algorithm to work. Also, variable i is not involved in your expression so what's it? Since Xn+1 is divided by n, I presume it can't be zero. Then the function should look like this:
double Avg(double[] array, int n)
{
if (n = 2)
{
return u1/2+array[2]; //u1 is a set value.
}
return (n-1)*Avg(array, n-1)/n+array[n]/(n-1);
}
Last but not least, it's more convenient to express recursive algorithm in µn = ... µ(n-1) instead of µ(n+1)=...µn.

Determine if all digits of the sum of n and swapped n are odd

I need to determine if all the digits of the sum of n numbers and swapped n are odd.
For example:
36 + 63 = 99 (9 and 9 are both odd)
409 + 904 = 1313 (1 and 3 are both odd)
Visual Studio builds my code and it runs, but it doesn't return an answer.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
long num = Convert.ToInt64(Console.Read());
long vol = voltea(num);
long sum = num + vol;
bool simp = simpares(sum);
if (simp == true)
Console.Write("Si");
else
Console.Write("No");
}
static private bool simpares(long x)
{
bool s = false;
long [] arreglo = new long [1000];
while ( x > 0)
{
arreglo [x % 10] ++;
x /=10;
}
for (long i=0 ; i <= arreglo.Length ; i++)
{
if (arreglo [i]%2 != 0)
s = true;
}
return s;
}
static private long voltea(long x)
{
long v = 0;
while (v > 0)
{
v = 10 * v + x % 10;
x /= 10;
}
return v;
}
}
}
I'm not sure what's wrong with your code, but I was thinking an easier way to accomplish this would be to use strings, rather than doing all the divisions and mods by 10.
Convert original number to string, reverse the string, then convert that back to a long
Add the original and reversed numbers
Convert the sum to a string
Loop over the result string and check to see if each digit is odd
It's not too clear what you mean by "Doesn't return an answer".
Add:
Console.ReadKey();
Console.ReadLine();
At the end of your Main function. I'd hazard a guess that you're not seeing an answer because the console is closing on you.
EDIT:
Found it:
for (long i=0 ; i <= arreglo.Length ; i++)
Index out of bounds. That should be:
for (long i=0 ; i < arreglo.Length ; i++)
i should be "Less than" arreglo, not "Less than or equal to"
EDIT2:
This is why your current code is broken. I'd highly recommend also looking at alternative methods of solving the problem. See Andy White's Answer.
It looks to me like you might have an infinite loop and a loop that never enters.
// because v = 0, the while will never execute
long v = 0;
while (v > 0)
{
v = 10 * v + x % 10;
x /= 10;
}

Categories