How to Implement The Sgn Function in C++?


C/C++, unfortunately, does not have a sgn function in its standard library however this is defined in the Boost library.

1
2
template <class T>
inline int sign (const T& z);
template <class T>
inline int sign (const T& z);
math-sgn-function-in-cpp How to Implement The Sgn Function in C++? c / c++ math programming languages

math-sgn-function-in-cpp

Very Basic Sgn Implementation

According to the above sgn graph, we can write something like this (assuming type double, and we can move to generics using template in C++ later).

1
2
3
4
5
int sgn(double v) {
  if (v < 0) return -1;
  if (v > 0) return 1;
  return 0;
}
int sgn(double v) {
  if (v < 0) return -1;
  if (v > 0) return 1;
  return 0;
}

Sgn function using C/C++ Ternary Operator

The above can be converted into one line using C/C++ Ternary Operator.

1
2
3
int sgn(double v) {
  return (v < 0) ? -1 : ((v > 0) ? 1 : 0);
}
int sgn(double v) {
  return (v < 0) ? -1 : ((v > 0) ? 1 : 0);
}

As bool (FALSE) is evaluated to zero and TRUE is equal to one, the above can be simplied to :

1
2
3
int sgn(double v) {
  return ( ( (v) < 0 )  ?  -1   : ( (v) > 0 ) )
}
int sgn(double v) {
  return ( ( (v) < 0 )  ?  -1   : ( (v) > 0 ) )
}

Of course, if you are using C compiler (which does not support templates/generics), you may want to use the Macro instead.

1
#define sgn(v) ( ( (v) < 0 ) ? -1 : ( (v) > 0 ) )
#define sgn(v) ( ( (v) < 0 ) ? -1 : ( (v) > 0 ) )

However in C++, we should prefer templates over macros.

Branchless Implementation

This simple task can be further improved using the following branchless expressions:

1
2
3
int sgn(double v) {
  return (v > 0) - (v < 0);
}
int sgn(double v) {
  return (v > 0) - (v < 0);
}

For example, if v=-1, above expression becomes (0) – 1 = -1, if v=0, above expression is evaluated to (0) – (0) = 0. The boolean (TRUE) is evaluated to 1 and boolean (FALSE) is evaluated to zero.

Make it Generics using Template

As the types can be of int, float, double etc, instead of overloading the Sgn functions for each type, we can make it generics using the template in C++.

1
2
3
4
5
template <class T>
inline int
sgn(T v) {
    return (v > T(0)) - (v < T(0));
}
template <class T>
inline int
sgn(T v) {
    return (v > T(0)) - (v < T(0));
}

The keyword class can be interchangable with typename in this case. The keyword inline makes it effient as the C++ compiler will inline this short code without actually calling it (which causes the stack frames creation and destruction).

The T(0) will be the zero value in that type, e.g. integer 0 or float 0.

Unit Test the Sgn function

We need to verify it before we have confidences to use it. So below are some good examples of the unit tests cases:

1
2
3
4
5
6
7
8
9
10
11
assertEquals(0, sgn(0));
assertEquals(0, sgn(0.0));
assertEquals(0, sgn(0.0f));
assertEquals(1, sgn(1.3f));
assertEquals(1, sgn(110));
assertEquals(1, sgn(0.0001f));
assertEquals(1, sgn(0.5));
assertEquals(-1, sgn(-0.0003));
assertEquals(-1, sgn(-9.0f));
assertEquals(-1, sgn(-234234));
assertEquals(-1, sgn(-1.00003f));
assertEquals(0, sgn(0));
assertEquals(0, sgn(0.0));
assertEquals(0, sgn(0.0f));
assertEquals(1, sgn(1.3f));
assertEquals(1, sgn(110));
assertEquals(1, sgn(0.0001f));
assertEquals(1, sgn(0.5));
assertEquals(-1, sgn(-0.0003));
assertEquals(-1, sgn(-9.0f));
assertEquals(-1, sgn(-234234));
assertEquals(-1, sgn(-1.00003f));

–EOF (The Ultimate Computing & Technology Blog) —

GD Star Rating
loading...
607 words
Last Post: C/C++ Coding Exercise - Convert a Number to Hexadecimal?
Next Post: How to Disable Ads on the Specific Posts?

The Permanent URL is: How to Implement The Sgn Function in C++?

Leave a Reply