2

I'm trying to re-write some MatLab code in C++ and I've come across this:

currentsign = sign(vector(i));

I have looked on the internet and found this link: http://www.mathworks.co.uk/help/techdoc/ref/sign.html

I'm just wondering if there's a sign function in C++? If not, can anyone suggest any tutorials on creating it.

Thank you :)

Phorce
  • 2,632
  • 13
  • 43
  • 76

5 Answers5

6
template <typename T>
int sign (const T &val) { return (val > 0) - (val < 0); }

Credit due to Ambroz Bizjak.

template <typename T>
std::vector<int> sign (const std::vector<T> &v) {
    std::vector<int> r(v.size());
    std::transform(v.begin(), v.end(), r.begin(), (int(*)(const T&))sign);
    return r;
}

Full example on ideone.

Community
  • 1
  • 1
jxh
  • 69,070
  • 8
  • 110
  • 193
4

I would suggest

First, write a function of functor that takes a single element and returns 1, -1 or 0 depending on the element's value

Second, use std::transform together with this function/functor to take an input container and fill a second container with the desired values

template <typename T>
int signum(const T& val) {
  // implement signum logic
}

#include <vector>
#include <algorithm>

int main() {

  std::vector<int> data = ....;
  std::vector<int> signs(data.size());
  std::transform(data.begin(), data.end(), signs.begin(), signum<int>);

}
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • Thank you. I'm an idiot and very tired. Didn't realise it was this simple ha - How do I mark these as solved? – Phorce Aug 16 '12 at 15:11
  • @user1582478 you have to select an answer. There is a tick symbol. next to each answer's score. When you select it in becomes green. – juanchopanza Aug 16 '12 at 15:28
1
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <vector>

inline int get_signum(int val) {
    return val < 0 ? -1
        : val == 0 ? 0
        : 1;
}

int main() {
    std::vector<int> values;
    for (int i = -5; i < 6; ++i)
        values.push_back(i);
    std::vector<int> signum(values.size());
    std::transform(values.begin(), values.end(), signum.begin(), get_signum);
    for (int i = 0; i < values.size(); ++i) {
        std::cout << std::setw(2) << values[i] << ' ' << signum[i] << std::endl;
    }
    return 0;
}
Pete Becker
  • 74,985
  • 8
  • 76
  • 165
1

Well You can do It at compile time using template Specialization.
You can use sign<n>::Positive, sign<n>::Negetive and sign<n>::Zero also you can use sign<n>::Sign which is 1|0|-1 which is same as sign of Matlab.

#include <iostream>

template<int n>
struct sign{
    enum{
      Positive = (n > 0),
      Negetive = (n < 0),
      Zero     = 0,
      Sign     = ((n > 0) ? 1 : -1)
    };
};

template<>
struct sign<0>{
    enum{
      Positive = 0,
      Negetive = 0,
      Zero     = 1,
      Sign     = 0
    };
};

int main(){
    std::cout << sign<0>::Positive  << sign<0>::Negetive  << sign<0>::Zero  << sign<0>::Sign  << std::endl;
    std::cout << sign<1>::Positive  << sign<1>::Negetive  << sign<1>::Zero  << sign<1>::Sign  << std::endl;
    std::cout << sign<-1>::Positive << sign<-1>::Negetive << sign<-1>::Zero << sign<-1>::Sign << std::endl;


    return 0;
}

You used to do sign(n) there and here you will do sign<n>::Sign.

Neel Basu
  • 12,638
  • 12
  • 82
  • 146
0

C99 has signbit() and copysign(), which seem to be implemented in glibc on Linux. You didn't specify what platform you're on though, so I'm not sure that helps...

twalberg
  • 59,951
  • 11
  • 89
  • 84