## 1. Overview

When working with numbers, we often encounter scenarios where we must check whether a given number is positive or negative.

In this tutorial, we’ll explore how to effectively check if a number is positive or negative in Kotlin. Further, we’ll build step by step an idiomatic function that works for all *Number* instances.

## 2. Introduction to the Problem

Determining whether an integer is positive or negative isn’t a challenge. However, Kotlin has various *Number* types, such as *Int, Long, Float, Double,* etc.

We aim to **create an idiomatic Kotlin number-checking function that reports whether a given number of any ***Number* type is positive, negative, or zero.

To make the verification easier, let’s create an enum class *NumberCategory:*

```
enum class NumberCategory {
Positive, Negative, Zero
}
```

So next, let’s start by checking *Int* numbers and achieving our goal step by step.

## 3. Using the *if-else* Expression

The most straightforward solution to determine whether a number is positive or negative would be comparing the number to *0*. We can use Kotlin’s *if-else* expression to implement it:

```
fun categoryOfInt1(n: Int): NumberCategory {
return if (n > 0) {
Positive
} else if (n < 0) {
Negative
} else {
Zero
}
}
```

As we can see, the code above is pretty straightforward. Next, let’s test if it can give the expected result if we pass different integers to the function:

```
assertEquals(Positive, categoryOfInt1(42))
assertEquals(Negative, categoryOfInt1(-42))
assertEquals(Zero, categoryOfInt1(0))
```

The test passes if we run it. Next, let’s make the code easier to read.

## 4. Using the *when* Expression

**Kotlin’s ***when* expression can often make code easier to read than *if-else* or *switch-case* expressions. So, let’s implement the *categoryOfInt* function in the *“when”* style:

```
fun categoryOfInt2(n: Int): NumberCategory {
return when {
n > 0 -> Positive
n < 0 -> Negative
else -> Zero
}
}
```

As the code above shows, the *when* expression makes the logic pretty clear. Next, let’s test with different inputs:

```
assertEquals(Positive, categoryOfInt2(42))
assertEquals(Negative, categoryOfInt2(-42))
assertEquals(Zero, categoryOfInt2(0))
```

The test passes if we give it a run. Therefore, the *“when”* style function solves the problem too.

## 5. Making the Function Available to All Numbers

Although the *“when”* style solution solves the problem elegantly, the function only supports *Int* objects. If we want to do the same check on other types, following the path, we’ll create a set of functions such as *categoryOfLong(), categoryOfFloat(), *etc.

Next, let’s **create one single function to support all kinds of ***Number* instances.

The *Number* class is an abstract class. It defines a series of functions to convert between concrete *Number* types, such as *toDouble(), toLong(), toInt()*, etc. In other words, when we receive a *Number* instance, no matter if it’s *Int, Long,* or *Byte, *we can convert it to a particular *Number* type.

**As ***Double* has the largest value range among all *Number* types, we can change the function argument type to *Number, *and convert the input to *Double*, then compare its value to *0* to get the result:

```
fun categoryOfNum(n: Number): NumberCategory {
val d = n.toDouble()
return when {
d > 0.0 -> Positive
d < 0.0 -> Negative
else -> Zero
}
}
```

We can verify the function using the following test:

```
// Int
assertEquals(Positive, categoryOfNum(42))
assertEquals(Negative, categoryOfNum(-42))
assertEquals(Zero, categoryOfNum(0))
// Long
assertEquals(Positive, categoryOfNum(42L))
assertEquals(Negative, categoryOfNum(-42L))
assertEquals(Zero, categoryOfNum(0L))
// Double
assertEquals(Positive, categoryOfNum(42.42))
assertEquals(Negative, categoryOfNum(-42.42))
assertEquals(Zero, categoryOfNum(0.00))
// Float
assertEquals(Positive, categoryOfNum(42.42f))
assertEquals(Negative, categoryOfNum(-42.42f))
assertEquals(Zero, categoryOfNum(0.00f))
```

## 6. Further Improvement: Using the Extension Function

We’ve created* categoryOfNum()* to support all *Number* types. But, when we call it, we must first write the function name and then the input. Next, **let’s make coding more fluent and natural by changing it into an extension function**:

```
fun Number.category(): NumberCategory {
val d = toDouble()
return when {
d > 0.0 -> Positive
d < 0.0 -> Negative
else -> Zero
}
}
```

This extension allows us to invoke the function as *42L.category(),* *(-42.42f).category()*, etc.:

```
// Int
assertEquals(Positive, 42.category())
assertEquals(Negative, (-42).category())
assertEquals(Zero, 0.category())
...
// Float
assertEquals(Positive, 42.42f.category())
assertEquals(Negative, (-42.42f).category())
assertEquals(Zero, 0.00f.category()
```

## 7. Conclusion

In this article, we’ve learned how to create an idiomatic solution to determine if a *Number* instance is positive, negative, or zero.

As always, the complete source code for the examples is available over on GitHub.