So, I'm writing a method that takes a user input and prints all of its prime factors. It works, except it's giving me a negative number at the end of every list. What is causing this??
static void PrimeFactors(int userInput)
{
// create a variable which is a new version of userInput that can be manipulated by the method
int input = userInput;
// declare a new list which will contain all of the factors of the user input.
var factors = new List<int>();
// While the input is greater than 1, if input mod counter is equal to 0,
// add counter to factor list and set input value to input / counter
// if input % counter != 0, break and start the for loop again
for(int counter = 1; input >= 1; )
{
if(input % counter == 0)
{
factors.Add(counter);
input = input / counter;
counter++;
}
else
{
counter++;
}
}
// display the prime factors
foreach (int factor in factors)
{
Console.Write($"{factor} ");
}
}
When I input 90, I get 1, 2, 3, 5, -3. When I input 31, I get 1, 31, -1. When I input 500, the output is 1, 2, 5, 10, -5. You get the point.
I know my code is not complete in terms of filtering ONLY prime factors, but I want to address these negative numbers before refining things to make sure only prime numbers get on the list.
The main problem is due to numeric overflow. In particular, your code doesn't have an appropriate exit condition, such as checking if
counter > input, in your loop code ofFor positive counter values where
input % counter == 0is true, thencounteris less than or equal toinput. Thus, the line of codeinput = input / counter;will haveinputstill be a positive integer, so theforloop check ofinput >= 1will always succeed. This means, sincecounteris a signed 32-bit integer, it'll continue increasing until it reaches Int32.MaxValue = 2147483647, i.e., 2^31 - 1. It then overflows with the high bit set to become the smallest negative integer value which is Int32.MinValue = -2147483648, i.e., -2^31. After that, it'll continue increasing until it gets to the negative of theinputvalue, in which case the linefactors.Add(counter);will add this negative value, andinput = input / counter;will causeinputto become -1, thus finally causing the loop to terminate.Thus, with your example of 90, the positive factors of 1, 2, 3, 5 multiply to 30, leaving a factor of 90 / 30 = 3 as the
inputvalue, which is why the final entry is -3. Similarly, with 31, there's just the factor of 31, soinputbecomes 1, resulting in a final list value of -1. Finally, with 500, the factors of 1, 2, 5, 10 multiply to 100. Thus, there's a remaining factor of 5, and so a final entry of -5 is in your list.A relatively simple fix is changing the
forloop condition check ofinput >= 1tocounter <= inputinstead. Also, although your code is not complete, as you state, one small suggestion is that since theforloop always incrementscounter, instead of doing that in two separate code lines as you do now, you can remove those lines and add that increment as the increment/decrement part of theforloop, e.g., have that line instead beRegarding your stated goal of finding and reporting on the prime factors, in addition to what I suggest above, there's a relatively simple set of changes you can make to your loop to accomplish this. In particular, just start with
counterat 2 (since 1 is not a prime) and insert this lineabove this line
This works because the first time the
ifcondition works,counterwill be the smallest prime factor ofinput. Then thewhileloop will remove all instances of that prime factor. Thus, each next value ofcounterwhich is a factor can't be composite since each of thecounterprime factors would have been removed earlier. Thus, the code will only be finding and adding prime factors to thefactorslist.Below is some sample code
which produces the output of