54

Just threw together a simple test, not for any particular reason other than I like to try to have tests for all my methods even though this one is quite straightforward, or so I thought.

    [TestMethod]
    public void Test_GetToolRating()
    {
        var rating = GetToolRating(45.5, 0);
        Assert.IsNotNull(rating);
    }


    private static ToolRating GetToolRating(double total, int numberOf)
    {
        var ratingNumber = 0.0;

        try
        {
            var tot = total / numberOf;
            ratingNumber = Math.Round(tot, 2);
        }
        catch (Exception ex)
        {
            var errorMessage = ex.Message;
            //log error here
            //var logger = new Logger();
            //logger.Log(errorMessage);
        }


        return GetToolRatingLevel(ratingNumber);
    }

As you can see in the test method, I AM dividing by zero. The problem is, it doesn't generate an error. See the error window display below.

Error List View from VS2017

Instead of an error it is giving a value of infinity? What am I missing?So I googled and found that doubles divided by zero DON'T generate an error they either give null or infinity. The question becomes then, how does one test for an Infinity return value?

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
dinotom
  • 4,990
  • 16
  • 71
  • 139
  • 22
    Yes, `1.0 / 0` is `double.PositiveInfinity` – Dmitry Bychenko May 30 '17 at 09:16
  • 1
    There are `float.PositiveInfinity` and `float.NegativeInfinity` in C#. (or `double.PositiveInfinity` and `double.NegativeInfinity`) – Silveris May 30 '17 at 09:18
  • 8
    **integers** will give an error when you try to divide by 0, floating point types do not. – Dennis_E May 30 '17 at 09:19
  • 1
    `float` & `double` has different behavior than `int` & `long` - it has `PositiveInfinity` & `NegativeInfinity` property while `int` & `long` will throw `DivideByZeroException` if dividing by zero occurs. – Tetsuya Yamamoto May 30 '17 at 09:20
  • 3
    There is a static `double.IsInfinity()` method to test for infinity. – C.Evenhuis May 30 '17 at 09:22
  • @TheLethalCoder...well I searched for that but wasn't looking for a property of double, which is probably why I didn't find it. Plus I was searching for Infinity, which is what the error window was showing, not PositiveInfinity – dinotom May 30 '17 at 13:29
  • A simple `Console.WriteLine` and `Debug.WriteLine` in your `catch` block would go a long way toward improving your code for use by other users. – jpmc26 May 30 '17 at 14:59
  • Double can't be null. You might want to google "C# class vs struct" as well. – Atomosk May 31 '17 at 03:30

2 Answers2

89

You are going to have DivideByZeroException only in case of integer values:

int total = 3;
int numberOf = 0;

var tot = total / numberOf; // DivideByZeroException thrown 

If at least one argument is a floating point value (double in the question) you'll have FloatingPointType.PositiveInfinity as a result (double.PositiveInfinity in the context) and no exception

double total = 3.0;
int numberOf = 0;

var tot = total / numberOf; // tot is double, tot == double.PositiveInfinity
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • 3
    and decimal as it doesn't have NaN and Infinity flags https://msdn.microsoft.com/en-us/library/system.decimal.divide – Slai May 30 '17 at 09:28
  • 1
    @Slai: You are quite right, thank you for the remark. But since `decimal` is a special case, (it's neither *integer* nor *floating point* type; but so called *binary coded decimal* - BCD) I've skipped it in my answer. – Dmitry Bychenko May 30 '17 at 09:34
  • 4
    To be pedantic, a negative numerator will return `double.NegativeInfinity`, and `0` as the numerator will return `double.NaN`. – IllusiveBrian May 30 '17 at 13:51
  • 1
    @IllusiveBrian well we should then also take into account the sign of zero, if it happens to be floating-point. – Ruslan May 30 '17 at 14:06
  • @Ruslan Based on [this test program](https://ideone.com/TloxZ2), division of zero by zero will return `double.NaN` regardless of the signs of the numerator and denominator. This is consistent with `C#`'s behavior of treating `0.0` as equivalent to `-0.0`. – IllusiveBrian May 30 '17 at 14:23
  • @IllusiveBrian I mean `1.3/-0.0`. Won't it be `-inf`? – Ruslan May 30 '17 at 14:23
  • @Ruslan I see, I updated the ideone script with that test case and `-1.3/-0.0`. It's kind of odd that the division operation takes the sign of zero into account for this, but it's a good thing to know. – IllusiveBrian May 30 '17 at 14:31
  • 1
    @IllusiveBrian IEEE 754 defines negative zero, hence `double` being able to distinguish it from positive zero. IEEE 754 also says it should be equal to positive zero for the usual comparisons (but allows that there may be other comparisons that distinguish them), hence `-0.0 == 0.0` returning true and `-0.0 < 0.0` returning false. – Jon Hanna May 30 '17 at 15:59
  • @JonHanna Right, but `(1.3/0.0) != (1.3/-0.0)`, as Ruslan pointed out. That the division operator does distinguish them is important in this context. – IllusiveBrian May 30 '17 at 17:01
  • @IllusiveBrian this is useful e.g. in the case of underflow to zero. The zero will remember the sign of the underflowing value. This division may be viewed as a one-sided limit with denominator→0±. – Ruslan May 30 '17 at 19:28
7

You may check like below

double total = 10.0;
double numberOf = 0.0;
var tot = total / numberOf;

// check for IsInfinity, IsPositiveInfinity,
// IsNegativeInfinity separately and take action appropriately if need be
if (double.IsInfinity(tot) || 
    double.IsPositiveInfinity(tot) || 
    double.IsNegativeInfinity(tot))
{
    ...
}
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
Shankar
  • 176
  • 7
  • 6
    `double.IsInfinity()` already tests for either the positive or negative versions, so you only need to check `if (double.IsInfinity(tot) ) { ... }`. [See docs here](https://msdn.microsoft.com/en-us/library/system.double.isinfinity(v=vs.110).aspx). – TripeHound May 30 '17 at 09:52
  • Thanks. I meant one may either check for IsInfinity or look out for specific infinity (positive or negative). Perhaps, my code comment is not reflecting this. – Shankar May 30 '17 at 09:57
  • 1
    Also what's the point of the post check when you could just pre check on the `numberOf` variable? – TheLethalCoder May 30 '17 at 12:48
  • That is true, but I believe IsInfinity exist for some very valid reasons... Otherwise everyone can just pre check the denominator. – Shankar May 30 '17 at 16:51
  • 2
    @TheLethalCoder Division by a nonzero divisor can still yield a result of infinity. Consider `1e300 / 1e-300`: two nonzero values, but the correct result of 1e600 is too large to fit into a `double`. – amalloy May 30 '17 at 18:24