0

I am trying to write a function that returns the outcome of multiplying all the negative numbers in an array. If the value is too large to be handled, I want it to return the int.MinValue.

I have coded this the following way, but it does not work correctly and I am not sure why.

public int MultiNeg(int[] array)
    {
        
        List<int> negativenumbers = new List<int>();

        foreach (int numbers in array)
        {
            if (numbers < 0)
                negativenumbers.Add(numbers);
        }


        int multiply = 1;

        foreach (int i in negativenumbers)
        {
                multiply = multiply * i;
                if (multiply > int.MaxValue)
            {
                return int.MinValue;
            }
            
        }

        if (multiply > int.MaxValue)
        {
            return int.MinValue;
        }
        else
        {
            return multiply;
        }
user3755632
  • 381
  • 1
  • 2
  • 20
  • 1
    don't you need `multiply` as an `int64` for this check? Or you can do a `try catch` block to see if you can multiply – StuiterSlurf Nov 20 '20 at 16:56
  • You should describe *how* it's "not working". Are you getting incorrect results? If so, what are the expected results and actual results you're seeing? Are you getting a compile error or runtime exception? If so, what is the error/exception message, and which line is causing it? – Rufus L Nov 20 '20 at 17:05
  • 1
    The condition: `if (multiply > int.MaxValue)` will always be `false`, It's impossible for an `int` to be greater then `int.MaxValue`. – Rufus L Nov 20 '20 at 17:08
  • This isn't what the question is asking, but have you considered using `int64` to properly cover the range without having to do this? Even if that's not enough, you could look at: https://learn.microsoft.com/en-us/dotnet/api/system.numerics.biginteger?view=net-5.0 – Everyone Nov 20 '20 at 17:12

2 Answers2

3

Instead of doing all this work, all you need to do the arithmetic as a checked expression and catch the exception to return the value of the failed case.

public static int MultiNeg(int[] array)
{
    var negativenumbers = array.Where(x => x < 0);

    int multiply = 1;

    foreach (int i in negativenumbers)
    {
        try {
            multiply = checked(multiply * i);
        }
        catch (OverflowException) {
            return Int32.MinValue;
        }
    }
    return multiply;
}

Bonus: Here's a condensed version using Linq's Aggregate method.

public static int MultiNeg(int[] array)
{
    try {
        return array.Where(x => x < 0).Aggregate(1, (x, y) => checked(x * y));
    } catch (OverflowException) {
        return Int32.MinValue;
    }
}
Daniel Gimenez
  • 18,530
  • 3
  • 50
  • 70
1

First, i can NEVER be > int.MaxValue since it is, itself, an int. Second, while @DanielGimenez has posted a perfectly working example, I am providing this alternative because the try-catch block will have negative impact on performance. If that is not important, then use his way. If it IS important, here is an alternative. Use Math.BigMul to get the result of the multiplication first (note the use of a long instead of an int for the result and comparison):

public int MultiNeg(int[] array)
{
    List<int> negativenumbers = new List<int>();
    foreach (int numbers in array)
    {
        if (numbers < 0)
            negativenumbers.Add(numbers);
    }
    int multiply = 1;
    foreach (int i in negativenumbers)
    {
        long value = Math.BigMul(multiply,i);
        if (value > int.MaxValue || value < int.MinValue)
        {
            return int.MinValue;
        }
        else
        {
            multiply = multiply * i;
        }
    }
    return multiply;
}

You will notice I also accounted for the case where multiply is < int.MinValue, which is equally possible and probable.

JesseChunn
  • 555
  • 3
  • 7