Is there a standard sign function (signum, sgn) in C/C++?
I want a function that returns -1 for negative numbers and +1 for positive numbers.
http://en.wikipedia.org/wiki/Sign_function
It's easy enough to write my own, but it seems like something that ought to be in a standard library somewhere.
Edit: Specifically, I was looking for a function working on floats.
c++ c math
|
show 5 more comments
I want a function that returns -1 for negative numbers and +1 for positive numbers.
http://en.wikipedia.org/wiki/Sign_function
It's easy enough to write my own, but it seems like something that ought to be in a standard library somewhere.
Edit: Specifically, I was looking for a function working on floats.
c++ c math
9
What should it return for 0?
– Craig McQueen
Dec 14 '09 at 23:26
51
@Craig McQueen; that depends on if it is a positive zero or negative zero.
– ysth
Dec 15 '09 at 5:53
1
I noticed that you specified the return value as an integer. Are you looking for a solution that takes integers or floating point numbers?
– Mark Byers
Dec 15 '09 at 9:56
4
@ysth @Craig McQueen, false for floats too, no? sgn(x)'s definition says to return 0 ifx==0
. According to IEEE 754, negative zero and positive zero should compare as equal.
– RJFalconer
Jun 4 '14 at 11:28
4
@ysth "it depends on positive zero or negative zero". In fact, it does not.
– RJFalconer
Jun 6 '14 at 8:10
|
show 5 more comments
I want a function that returns -1 for negative numbers and +1 for positive numbers.
http://en.wikipedia.org/wiki/Sign_function
It's easy enough to write my own, but it seems like something that ought to be in a standard library somewhere.
Edit: Specifically, I was looking for a function working on floats.
c++ c math
I want a function that returns -1 for negative numbers and +1 for positive numbers.
http://en.wikipedia.org/wiki/Sign_function
It's easy enough to write my own, but it seems like something that ought to be in a standard library somewhere.
Edit: Specifically, I was looking for a function working on floats.
c++ c math
c++ c math
edited Dec 24 '09 at 2:40
batty
asked Dec 14 '09 at 22:27
battybatty
3,06492630
3,06492630
9
What should it return for 0?
– Craig McQueen
Dec 14 '09 at 23:26
51
@Craig McQueen; that depends on if it is a positive zero or negative zero.
– ysth
Dec 15 '09 at 5:53
1
I noticed that you specified the return value as an integer. Are you looking for a solution that takes integers or floating point numbers?
– Mark Byers
Dec 15 '09 at 9:56
4
@ysth @Craig McQueen, false for floats too, no? sgn(x)'s definition says to return 0 ifx==0
. According to IEEE 754, negative zero and positive zero should compare as equal.
– RJFalconer
Jun 4 '14 at 11:28
4
@ysth "it depends on positive zero or negative zero". In fact, it does not.
– RJFalconer
Jun 6 '14 at 8:10
|
show 5 more comments
9
What should it return for 0?
– Craig McQueen
Dec 14 '09 at 23:26
51
@Craig McQueen; that depends on if it is a positive zero or negative zero.
– ysth
Dec 15 '09 at 5:53
1
I noticed that you specified the return value as an integer. Are you looking for a solution that takes integers or floating point numbers?
– Mark Byers
Dec 15 '09 at 9:56
4
@ysth @Craig McQueen, false for floats too, no? sgn(x)'s definition says to return 0 ifx==0
. According to IEEE 754, negative zero and positive zero should compare as equal.
– RJFalconer
Jun 4 '14 at 11:28
4
@ysth "it depends on positive zero or negative zero". In fact, it does not.
– RJFalconer
Jun 6 '14 at 8:10
9
9
What should it return for 0?
– Craig McQueen
Dec 14 '09 at 23:26
What should it return for 0?
– Craig McQueen
Dec 14 '09 at 23:26
51
51
@Craig McQueen; that depends on if it is a positive zero or negative zero.
– ysth
Dec 15 '09 at 5:53
@Craig McQueen; that depends on if it is a positive zero or negative zero.
– ysth
Dec 15 '09 at 5:53
1
1
I noticed that you specified the return value as an integer. Are you looking for a solution that takes integers or floating point numbers?
– Mark Byers
Dec 15 '09 at 9:56
I noticed that you specified the return value as an integer. Are you looking for a solution that takes integers or floating point numbers?
– Mark Byers
Dec 15 '09 at 9:56
4
4
@ysth @Craig McQueen, false for floats too, no? sgn(x)'s definition says to return 0 if
x==0
. According to IEEE 754, negative zero and positive zero should compare as equal.– RJFalconer
Jun 4 '14 at 11:28
@ysth @Craig McQueen, false for floats too, no? sgn(x)'s definition says to return 0 if
x==0
. According to IEEE 754, negative zero and positive zero should compare as equal.– RJFalconer
Jun 4 '14 at 11:28
4
4
@ysth "it depends on positive zero or negative zero". In fact, it does not.
– RJFalconer
Jun 6 '14 at 8:10
@ysth "it depends on positive zero or negative zero". In fact, it does not.
– RJFalconer
Jun 6 '14 at 8:10
|
show 5 more comments
23 Answers
23
active
oldest
votes
Surprised no one has posted the branchless, type-safe C++ version yet:
template <typename T> int sgn(T val) {
return (T(0) < val) - (val < T(0));
}
Benefits:
- Actually implements signum (-1, 0, or 1). Implementations here using copysign only return -1 or 1, which is not signum. Also, some implementations here are returning a float (or T) rather than an int, which seems wasteful.
- Works for ints, floats, doubles, unsigned shorts, or any custom types constructible from integer 0 and orderable.
- Fast!
copysign
is slow, especially if you need to promote and then narrow again. This is branchless and optimizes excellently - Standards-compliant! The bitshift hack is neat, but only works for some bit representations, and doesn't work when you have an unsigned type. It could be provided as a manual specialization when appropriate.
- Accurate! Simple comparisons with zero can maintain the machine's internal high-precision representation (e.g. 80 bit on x87), and avoid a premature round to zero.
Caveats:
- It's a template so it'll take forever to compile.
- Apparently some people think use of a new, somewhat esoteric, and very slow standard library function that doesn't even really implement signum is more understandable.
The
< 0
part of the check triggers GCC's-Wtype-limits
warning when instantiated for an unsigned type. You can avoid this by using some overloads:
template <typename T> inline constexpr
int signum(T x, std::false_type is_signed) {
return T(0) < x;
}
template <typename T> inline constexpr
int signum(T x, std::true_type is_signed) {
return (T(0) < x) - (x < T(0));
}
template <typename T> inline constexpr
int signum(T x) {
return signum(x, std::is_signed<T>());
}
(Which is a good example of the first caveat.)
16
@GMan: GCC only just now (4.5) stopped having cost quadratic to the number of instantiations for template functions, and they are still drastically more expensive to parse and instantiate than manually written functions or the standard C preprocessor. The linker also has to do more work to remove duplicate instantiations. Templates also encourage #includes-in-#includes, which makes dependency calculation take longer and small (often implementation, not interface) changes to force more files to be recompiled.
– user79758
Jan 5 '11 at 22:42
14
@Joe: Yes, and there's still no noticeable cost. C++ uses templates, that's just something we all have to understand, accept, and get over.
– GManNickG
Jan 5 '11 at 22:54
36
Wait, what's this "copysign is slow" business...? Using current compilers (g++ 4.6+, clang++ 3.0),std::copysign
seems to result in excellent code for me: 4 instructions (inlined), no branching, entirely using the FPU. The recipe given in this answer, by contrast, generates much worse code (many more instructions, including a multiply, moving back and forth between integer unit and FPU)...
– snogglethorpe
Jan 23 '12 at 6:35
13
@snogglethorpe: If you're callingcopysign
on an int it promotes to float/double, and must narrow again on return. Your compiler may optimize that promotion out but I can't find anything suggesting that's guaranteed by the standard. Also to implement signum via copysign you need to manually handle the 0 case - please make sure you include that in any performance comparison.
– user79758
Jan 23 '12 at 9:31
42
The first version is not branchless. Why do people think that a comparison used in an expression will not generate a branch? It will on most architectures. Only processors that have a cmove (or predication) will generate branchless code, but they'll do it also for ternaries or if/else if it is a win.
– Patrick Schlüter
Mar 12 '12 at 15:41
|
show 18 more comments
I don't know of a standard function for it. Here's an interesting way to write it though:
(x > 0) - (x < 0)
Here's a more readable way to do it:
if (x > 0) return 1;
if (x < 0) return -1;
return 0;
If you like the ternary operator you can do this:
(x > 0) ? 1 : ((x < 0) ? -1 : 0)
6
Also one that works without branches. Nice.
– Joey
Dec 14 '09 at 22:31
6
Mark Ransom, your expressions give incorrect results forx==0
.
– avakar
Dec 14 '09 at 22:45
10
@Svante: not exactly. A value of0
is "false"; any other value is "true"; however, the relational and equality operators always return0
or1
(see Standard 6.5.8 and 6.5.9). -- the value of the expressiona * (x == 42)
is either0
ora
.
– pmg
Dec 14 '09 at 23:21
21
High-Performance Mark, I'm amazed that you missed the C++ tag. This answer is very much valid and doesn't deserve a down-vote. Moreover, I wouldn't usecopysign
for integralx
even if I had it available.
– avakar
Dec 15 '09 at 8:39
4
Has anyone actually checked what code GCC/G++/any other compiler emits on a real platform? My guess is that the "branchless" version uses two branches instead of one. Bitshifting is probably a lot faster - and more portable in terms of performance.
– Jørgen Fogh
Sep 2 '11 at 11:29
|
show 18 more comments
There is a C99 math library function called copysign(), which takes the sign from one argument and the absolute value from the other:
result = copysign(1.0, value) // double
result = copysignf(1.0, value) // float
result = copysignl(1.0, value) // long double
will give you a result of +/- 1.0, depending on the sign of value. Note that floating point zeroes are signed: (+0) will yield +1, and (-0) will yield -1.
51
Upvoted this one, downvoted most popular answer. Left reeling in amazement that SO community seems to prefer a hack to use of a standard library function. May the gods of programming condemn you all to trying to decipher hacks used by clever programmers unfamiliar with language standards. Yeah, I know this is going to cost me a ton of rep on SO, but I'd rather side with comingstorm than the rest of you ...
– High Performance Mark
Dec 15 '09 at 7:42
26
This is close, but it gives the wrong answer for zero (according to the Wikipedia article in the question at least). Nice suggestion though. +1 anyway.
– Mark Byers
Dec 15 '09 at 8:25
4
If you want an integer, or if you want the exact signum result for zeros, I like Mark Byers' answer, which is fiendishly elegant! If you don't care about the above, copysign() might have a performance advanage, depending on the application -- if I were optimizing a critical loop, I would try both.
– comingstorm
Dec 16 '09 at 10:08
10
1) C99 is not fully supported everywhere (consider VC++); 2) this is also a C++ question. This is a good answer, but the upvoted one also works, and is more widely applicable.
– Pavel Minaev
Dec 31 '09 at 9:17
5
Savior! Needed a way to determine between -0.0 and 0.0
– Ólafur Waage
May 14 '11 at 13:32
|
show 4 more comments
Apparently, the answer to the original poster's question is no. There is no standard C++ sgn
function.
2
Actually there is one : en.cppreference.com/w/cpp/numeric/math/copysign. Use : std::copysign(1, x); Note that the return type is not integral.
– SR_
Nov 14 '17 at 12:15
add a comment |
It seems that most of the answers missed the original question.
Is there a standard sign function (signum, sgn) in C/C++?
Not in the standard library, but there is in boost
, which might as well be part of the standard.
#include <boost/math/special_functions/sign.hpp>
//Returns 1 if x > 0, -1 if x < 0, and 0 if x is zero.
template <class T>
inline int sign (const T& z);
http://www.boost.org/doc/libs/1_47_0/libs/math/doc/sf_and_dist/html/math_toolkit/utils/sign_functions.html
4
This should be the most top-voted answer, as it gives the closest possible solution to what's asked in the question.
– BartoszKP
Mar 20 '15 at 14:20
I have been wondering for the past few minutes why the standard library doesn't have sign function. It is just so common -- definitely more commonly used than gamma function which could be found in cmath header.
– Taozi
Feb 22 '16 at 22:33
3
The explanation I often get for similar questions is "it's easy enough to implement yourself" Which IMO is not a good reason. It completely belies the problems of where standardization, unobvious edge cases, and where to put such a widely used tool.
– Catskul
Feb 22 '16 at 22:35
add a comment |
Faster than the above solutions, including the highest rated one:
(x < 0) ? -1 : (x > 0)
What type is x? Or are you using a #define?
– Chance
Feb 20 '12 at 18:11
3
Your type is not faster. It will cause a cache miss quite often.
– Jeffrey Drake
Dec 30 '12 at 3:19
16
Cache miss? I'm not sure how. Perhaps you meant branch misprediction?
– Catskul
Jun 1 '13 at 5:10
1
It seems to me this will result in a warning of confusing integer and boolean types!
– sergiol
Sep 2 '15 at 11:55
how this will be fast with the branch?
– Nick
Jul 15 '17 at 19:55
add a comment |
Is there a standard sign function (signum, sgn) in C/C++?
Yes, depending on definition.
C99 and later has the signbit()
macro in <math.h>
int signbit
(real-floatingx
);
Thesignbit
macro returns a nonzero value if and only if the sign of its argument value is negative. C11 §7.12.3.6
Yet OP wants something a little different.
I want a function that returns -1 for negative numbers and +1 for positive numbers. ... a function working on floats.
#define signbit_p1_or_n1(x) ((signbit(x) ? -1 : 1)
Deeper:
The post is not specific in the following cases, x = 0.0, -0.0, +NaN, -NaN
.
A classic signum()
returns +1
on x>0
, -1
on x>0
and 0
on x==0
.
Many answers have already covered that, but do not address x = -0.0, +NaN, -NaN
. Many are geared for an integer point-of-view that usually lacks Not-a-Numbers (NaN) and -0.0.
Typical answers function like signnum_typical()
On -0.0, +NaN, -NaN
, they return 0.0, 0.0, 0.0
.
int signnum_typical(double x) {
if (x > 0.0) return 1;
if (x < 0.0) return -1;
return 0;
}
Instead, propose this functionality: On -0.0, +NaN, -NaN
, it returns -0.0, +NaN, -NaN
.
double signnum_c(double x) {
if (x > 0.0) return 1.0;
if (x < 0.0) return -1.0;
return x;
}
1
Ah, exactly what I'm after. This just changed in Pharo Smalltalk github.com/pharo-project/pharo/pull/1835 and I wondered if there was some sort of standard (IEC 60559 or ISO 10967) dictating behavior for negative zero and nan behaviour... I like the javascript sign developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
– aka.nice
Sep 30 '18 at 19:27
add a comment |
There's a way to do it without branching, but it's not very pretty.
sign = -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
http://graphics.stanford.edu/~seander/bithacks.html
Lots of other interesting, overly-clever stuff on that page, too...
1
If I read the link correctly that only returns -1 or 0. If you want -1, 0, or +1 then it'ssign = (v != 0) | -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
orsign = (v > 0) - (v < 0);
.
– Z boson
Apr 21 '15 at 7:58
1
Not exactly what we call portable code...
– flederwiesel
Dec 1 '16 at 18:18
add a comment |
If all you want is to test the sign, use signbit (returns true if its argument has a negative sign).
Not sure why you would particularly want -1 or +1 returned; copysign is more convenient
for that, but it sounds like it will return +1 for negative zero on some platforms with
only partial support for negative zero, where signbit presumably would return true.
5
There's many mathematical applications in which the sign(x) is necessary. Otherwise I'd just doif (x < 0)
.
– Chance
Mar 9 '12 at 16:42
add a comment |
In general, there is no standard signum function in C/C++, and the lack of such a fundamental function tells you a lot about these languages.
Apart from that, I believe both majority viewpoints about the right approach to define such a function are in a way correct, and the "controversy" about it is actually a non-argument once you take into account two important caveats:
A signum function should always return the type of its operand, similarly to an
abs()
function, because signum is usually used for multiplication with an absolute value after the latter has been processed somehow. Therefore, the major use case of signum is not comparisons but arithmetic, and the latter shouldn't involve any expensive integer-to/from-floating-point conversions.Floating point types do not feature a single exact zero value: +0.0 can be interpreted as "infinitesimally above zero", and -0.0 as "infinitesimally below zero". That's the reason why comparisons involving zero must internally check against both values, and an expression like
x == 0.0
can be dangerous.
Regarding C, I think the best way forward with integral types is indeed to use the (x > 0) - (x < 0)
expression, as it should be translated in a branch-free fashion, and requires only three basic operations. Best define inline functions that enforce a return type matching the argument type, and add a C11 define _Generic
to map these functions to a common name.
With floating point values, I think inline functions based on C11 copysignf(1.0f, x)
, copysign(1.0, x)
, and copysignl(1.0l, x)
are the way to go, simply because they're also highly likely to be branch-free, and additionally do not require casting the result from integer back into a floating point value. You should probably comment prominently that your floating point implementations of signum will not return zero because of the peculiarities of floating point zero values, processing time considerations, and also because it is often very useful in floating point arithmetic to receive the correct -1/+1 sign, even for zero values.
add a comment |
My copy of C in a Nutshell reveals the existence of a standard function called copysign which might be useful. It looks as if copysign(1.0, -2.0) would return -1.0 and copysign(1.0, 2.0) would return +1.0.
Pretty close huh?
Not standard, but may be widely available. Microsoft's starts with an underscore, which is the convention they use for non-standard extensions. Not the best choice when you're working with integers, though.
– Mark Ransom
Dec 14 '09 at 23:33
5
copysign is both in the ISO C (C99) and POSIX standards. See opengroup.org/onlinepubs/000095399/functions/copysign.html
– lhf
Dec 15 '09 at 1:19
3
What lhf said. Visual Studio is not a reference for the C standard.
– Stephen Canon
Dec 15 '09 at 1:42
add a comment |
No, it doesn't exist in c++, like in matlab. I use a macro in my programs for this.
#define sign(a) ( ( (a) < 0 ) ? -1 : ( (a) > 0 ) )
4
One should prefer templates over macros in C++.
– Ruslan
Jan 27 '16 at 11:06
In C, there is no template ...... helloacm.com/how-to-implement-the-sgn-function-in-c
– justyy
Oct 20 '16 at 10:55
I thought this was a good answer then I looked at my own code and found this:#define sign(x) (((x) > 0) - ((x) < 0))
which is good too.
– Michel Rouzic
Feb 25 '18 at 12:12
1
an inline function is better than a macro in C, and in C++ template is better
– phuclv
Apr 10 '18 at 16:05
add a comment |
The accepted Answer with the overload below does indeed not trigger -Wtype-limits however it triggers -Wunused-parameter on the is_signed
argument.
template <typename T> inline constexpr
int signum(T x, std::false_type is_signed) {
return T(0) < x;
}
template <typename T> inline constexpr
int signum(T x, std::true_type is_signed) {
return (T(0) < x) - (x < T(0));
}
template <typename T> inline constexpr
int signum(T x) {
return signum(x, std::is_signed<T>());
}
For C++11 an alternative could be.
template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, int>::type
inline constexpr signum(T x) {
return T(0) < x;
}
template <typename T>
typename std::enable_if<std::is_signed<T>::value, int>::type
inline constexpr signum(T x) {
return (T(0) < x) - (x < T(0));
}
For me it does not trigger any warnings on GCC 5.3.1
To avoid the-Wunused-parameter
warning just use unnamed parameters.
– Jonathan Wakely
Jan 24 at 12:47
That is actually very true. I missed that. However, I like the C++11 alternative more either way.
– SamVanDonut
yesterday
add a comment |
Bit off-topic, but I use this:
template<typename T>
constexpr int sgn(const T &a, const T &b) noexcept{
return (a > b) - (a < b);
}
template<typename T>
constexpr int sgn(const T &a) noexcept{
return sgn(a, T(0));
}
and I found first function - the one with two arguments, to be much more useful from "standard" sgn(), because it is most often used in code like this:
int comp(unsigned a, unsigned b){
return sgn( int(a) - int(b) );
}
vs.
int comp(unsigned a, unsigned b){
return sgn(a, b);
}
there is no cast for unsigned types and no additional minus.
in fact i have this piece of code using sgn()
template <class T>
int comp(const T &a, const T &b){
log__("all");
if (a < b)
return -1;
if (a > b)
return +1;
return 0;
}
inline int comp(int const a, int const b){
log__("int");
return a - b;
}
inline int comp(long int const a, long int const b){
log__("long");
return sgn(a, b);
}
add a comment |
You can use boost::math::sign()
method from boost/math/special_functions/sign.hpp
if boost is available.
Note that this was suggested before: stackoverflow.com/a/16869019/1187415.
– Martin R
Aug 29 '18 at 8:41
add a comment |
int sign(float n)
{
union { float f; std::uint32_t i; } u { n };
return 1 - ((u.i >> 31) << 1);
}
This function assumes:
binary32 representation of floating point numbers- a compiler that make an exception about the strict aliasing rule when using a named union
3
There are still some bad assumptions here. For example I don't believe the endianness of the float is guaranteed to be the endianness of the integer. Your check also fails on any architectures using ILP64. Really, you're just reimplementingcopysign
; if you're usingstatic_assert
you've got C++11, and might as well really usecopysign
.
– user79758
Mar 15 '12 at 18:24
add a comment |
While the integer solution in the accepted answer is quite elegant it bothered me that it wouldn't be able to return NAN for double types, so I modified it slightly.
template <typename T> double sgn(T val) {
return double((T(0) < val) - (val < T(0)))/(val == val);
}
Note that returning a floating point NAN as opposed to a hard coded NAN
causes the sign bit to be set in some implementations, so the output for val = -NAN
and val = NAN
are going to be identical no matter what (if you prefer a "nan
" output over a -nan
you can put an abs(val)
before the return...)
add a comment |
Here's a branching-friendly implementation:
inline int signum(const double x) {
if(x == 0) return 0;
return (1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}
Unless your data has zeros as half of the numbers, here the branch predictor will choose one of the branches as the most common. Both branches only involve simple operations.
Alternatively, on some compilers and CPU architectures a completely branchless version may be faster:
inline int signum(const double x) {
return (x != 0) *
(1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}
This works for IEEE 754 double-precision binary floating-point format: binary64 .
add a comment |
Why use ternary operators and if-else when you can simply do this
#define sgn(x) x==0 ? 0 : x/abs(x)
1
Your definition uses a ternary operator as well.
– Martin R
Jun 30 '18 at 14:26
Yes Definitely, but it just uses one ternary operator to separate zero and non-zero numbers. Others' versions include nested ternary ops to separate positive, negative and zero.
– Jagreet
Jun 30 '18 at 16:15
add a comment |
double signof(double a) { return (a == 0) ? 0 : (a<0 ? -1 : 1); }
add a comment |
I ran into this just today. So fine, there's no standard way but...
Since the OP just needed to magnify the output range and re-centre it on 0, (-1 to 1 not 0 to 1) why not just double it and subtract 1?
I used this:
(x<0)*2-1
Or, forcing a bit shift:
(x<0)<<1-1
But the compiler will likely optimize that anyway.
add a comment |
What about:
int sgn = x/fabs(x);
it should work out pretty good.
5
What happens when x == 0.0 ?
– Paul R
Jun 20 '17 at 7:30
1
and the performance would be pretty bad, too
– phuclv
Jun 30 '18 at 3:26
add a comment |
use:
`#define sgn(x) (x<0)`
for example:
`if(sng(n)) { etc ....}`
Or you may want to use some elaborated code, but casting first:
inline bool sgn_long(long x)
{
return ((x<0)? true: false);
}
1
The question was about a function that returns -1/0/+1 for negative/zero/positive numbers.
– Martin R
Nov 17 '17 at 10:03
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f1903954%2fis-there-a-standard-sign-function-signum-sgn-in-c-c%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
23 Answers
23
active
oldest
votes
23 Answers
23
active
oldest
votes
active
oldest
votes
active
oldest
votes
Surprised no one has posted the branchless, type-safe C++ version yet:
template <typename T> int sgn(T val) {
return (T(0) < val) - (val < T(0));
}
Benefits:
- Actually implements signum (-1, 0, or 1). Implementations here using copysign only return -1 or 1, which is not signum. Also, some implementations here are returning a float (or T) rather than an int, which seems wasteful.
- Works for ints, floats, doubles, unsigned shorts, or any custom types constructible from integer 0 and orderable.
- Fast!
copysign
is slow, especially if you need to promote and then narrow again. This is branchless and optimizes excellently - Standards-compliant! The bitshift hack is neat, but only works for some bit representations, and doesn't work when you have an unsigned type. It could be provided as a manual specialization when appropriate.
- Accurate! Simple comparisons with zero can maintain the machine's internal high-precision representation (e.g. 80 bit on x87), and avoid a premature round to zero.
Caveats:
- It's a template so it'll take forever to compile.
- Apparently some people think use of a new, somewhat esoteric, and very slow standard library function that doesn't even really implement signum is more understandable.
The
< 0
part of the check triggers GCC's-Wtype-limits
warning when instantiated for an unsigned type. You can avoid this by using some overloads:
template <typename T> inline constexpr
int signum(T x, std::false_type is_signed) {
return T(0) < x;
}
template <typename T> inline constexpr
int signum(T x, std::true_type is_signed) {
return (T(0) < x) - (x < T(0));
}
template <typename T> inline constexpr
int signum(T x) {
return signum(x, std::is_signed<T>());
}
(Which is a good example of the first caveat.)
16
@GMan: GCC only just now (4.5) stopped having cost quadratic to the number of instantiations for template functions, and they are still drastically more expensive to parse and instantiate than manually written functions or the standard C preprocessor. The linker also has to do more work to remove duplicate instantiations. Templates also encourage #includes-in-#includes, which makes dependency calculation take longer and small (often implementation, not interface) changes to force more files to be recompiled.
– user79758
Jan 5 '11 at 22:42
14
@Joe: Yes, and there's still no noticeable cost. C++ uses templates, that's just something we all have to understand, accept, and get over.
– GManNickG
Jan 5 '11 at 22:54
36
Wait, what's this "copysign is slow" business...? Using current compilers (g++ 4.6+, clang++ 3.0),std::copysign
seems to result in excellent code for me: 4 instructions (inlined), no branching, entirely using the FPU. The recipe given in this answer, by contrast, generates much worse code (many more instructions, including a multiply, moving back and forth between integer unit and FPU)...
– snogglethorpe
Jan 23 '12 at 6:35
13
@snogglethorpe: If you're callingcopysign
on an int it promotes to float/double, and must narrow again on return. Your compiler may optimize that promotion out but I can't find anything suggesting that's guaranteed by the standard. Also to implement signum via copysign you need to manually handle the 0 case - please make sure you include that in any performance comparison.
– user79758
Jan 23 '12 at 9:31
42
The first version is not branchless. Why do people think that a comparison used in an expression will not generate a branch? It will on most architectures. Only processors that have a cmove (or predication) will generate branchless code, but they'll do it also for ternaries or if/else if it is a win.
– Patrick Schlüter
Mar 12 '12 at 15:41
|
show 18 more comments
Surprised no one has posted the branchless, type-safe C++ version yet:
template <typename T> int sgn(T val) {
return (T(0) < val) - (val < T(0));
}
Benefits:
- Actually implements signum (-1, 0, or 1). Implementations here using copysign only return -1 or 1, which is not signum. Also, some implementations here are returning a float (or T) rather than an int, which seems wasteful.
- Works for ints, floats, doubles, unsigned shorts, or any custom types constructible from integer 0 and orderable.
- Fast!
copysign
is slow, especially if you need to promote and then narrow again. This is branchless and optimizes excellently - Standards-compliant! The bitshift hack is neat, but only works for some bit representations, and doesn't work when you have an unsigned type. It could be provided as a manual specialization when appropriate.
- Accurate! Simple comparisons with zero can maintain the machine's internal high-precision representation (e.g. 80 bit on x87), and avoid a premature round to zero.
Caveats:
- It's a template so it'll take forever to compile.
- Apparently some people think use of a new, somewhat esoteric, and very slow standard library function that doesn't even really implement signum is more understandable.
The
< 0
part of the check triggers GCC's-Wtype-limits
warning when instantiated for an unsigned type. You can avoid this by using some overloads:
template <typename T> inline constexpr
int signum(T x, std::false_type is_signed) {
return T(0) < x;
}
template <typename T> inline constexpr
int signum(T x, std::true_type is_signed) {
return (T(0) < x) - (x < T(0));
}
template <typename T> inline constexpr
int signum(T x) {
return signum(x, std::is_signed<T>());
}
(Which is a good example of the first caveat.)
16
@GMan: GCC only just now (4.5) stopped having cost quadratic to the number of instantiations for template functions, and they are still drastically more expensive to parse and instantiate than manually written functions or the standard C preprocessor. The linker also has to do more work to remove duplicate instantiations. Templates also encourage #includes-in-#includes, which makes dependency calculation take longer and small (often implementation, not interface) changes to force more files to be recompiled.
– user79758
Jan 5 '11 at 22:42
14
@Joe: Yes, and there's still no noticeable cost. C++ uses templates, that's just something we all have to understand, accept, and get over.
– GManNickG
Jan 5 '11 at 22:54
36
Wait, what's this "copysign is slow" business...? Using current compilers (g++ 4.6+, clang++ 3.0),std::copysign
seems to result in excellent code for me: 4 instructions (inlined), no branching, entirely using the FPU. The recipe given in this answer, by contrast, generates much worse code (many more instructions, including a multiply, moving back and forth between integer unit and FPU)...
– snogglethorpe
Jan 23 '12 at 6:35
13
@snogglethorpe: If you're callingcopysign
on an int it promotes to float/double, and must narrow again on return. Your compiler may optimize that promotion out but I can't find anything suggesting that's guaranteed by the standard. Also to implement signum via copysign you need to manually handle the 0 case - please make sure you include that in any performance comparison.
– user79758
Jan 23 '12 at 9:31
42
The first version is not branchless. Why do people think that a comparison used in an expression will not generate a branch? It will on most architectures. Only processors that have a cmove (or predication) will generate branchless code, but they'll do it also for ternaries or if/else if it is a win.
– Patrick Schlüter
Mar 12 '12 at 15:41
|
show 18 more comments
Surprised no one has posted the branchless, type-safe C++ version yet:
template <typename T> int sgn(T val) {
return (T(0) < val) - (val < T(0));
}
Benefits:
- Actually implements signum (-1, 0, or 1). Implementations here using copysign only return -1 or 1, which is not signum. Also, some implementations here are returning a float (or T) rather than an int, which seems wasteful.
- Works for ints, floats, doubles, unsigned shorts, or any custom types constructible from integer 0 and orderable.
- Fast!
copysign
is slow, especially if you need to promote and then narrow again. This is branchless and optimizes excellently - Standards-compliant! The bitshift hack is neat, but only works for some bit representations, and doesn't work when you have an unsigned type. It could be provided as a manual specialization when appropriate.
- Accurate! Simple comparisons with zero can maintain the machine's internal high-precision representation (e.g. 80 bit on x87), and avoid a premature round to zero.
Caveats:
- It's a template so it'll take forever to compile.
- Apparently some people think use of a new, somewhat esoteric, and very slow standard library function that doesn't even really implement signum is more understandable.
The
< 0
part of the check triggers GCC's-Wtype-limits
warning when instantiated for an unsigned type. You can avoid this by using some overloads:
template <typename T> inline constexpr
int signum(T x, std::false_type is_signed) {
return T(0) < x;
}
template <typename T> inline constexpr
int signum(T x, std::true_type is_signed) {
return (T(0) < x) - (x < T(0));
}
template <typename T> inline constexpr
int signum(T x) {
return signum(x, std::is_signed<T>());
}
(Which is a good example of the first caveat.)
Surprised no one has posted the branchless, type-safe C++ version yet:
template <typename T> int sgn(T val) {
return (T(0) < val) - (val < T(0));
}
Benefits:
- Actually implements signum (-1, 0, or 1). Implementations here using copysign only return -1 or 1, which is not signum. Also, some implementations here are returning a float (or T) rather than an int, which seems wasteful.
- Works for ints, floats, doubles, unsigned shorts, or any custom types constructible from integer 0 and orderable.
- Fast!
copysign
is slow, especially if you need to promote and then narrow again. This is branchless and optimizes excellently - Standards-compliant! The bitshift hack is neat, but only works for some bit representations, and doesn't work when you have an unsigned type. It could be provided as a manual specialization when appropriate.
- Accurate! Simple comparisons with zero can maintain the machine's internal high-precision representation (e.g. 80 bit on x87), and avoid a premature round to zero.
Caveats:
- It's a template so it'll take forever to compile.
- Apparently some people think use of a new, somewhat esoteric, and very slow standard library function that doesn't even really implement signum is more understandable.
The
< 0
part of the check triggers GCC's-Wtype-limits
warning when instantiated for an unsigned type. You can avoid this by using some overloads:
template <typename T> inline constexpr
int signum(T x, std::false_type is_signed) {
return T(0) < x;
}
template <typename T> inline constexpr
int signum(T x, std::true_type is_signed) {
return (T(0) < x) - (x < T(0));
}
template <typename T> inline constexpr
int signum(T x) {
return signum(x, std::is_signed<T>());
}
(Which is a good example of the first caveat.)
edited Mar 28 '12 at 13:58
answered Jan 5 '11 at 22:19
user79758
16
@GMan: GCC only just now (4.5) stopped having cost quadratic to the number of instantiations for template functions, and they are still drastically more expensive to parse and instantiate than manually written functions or the standard C preprocessor. The linker also has to do more work to remove duplicate instantiations. Templates also encourage #includes-in-#includes, which makes dependency calculation take longer and small (often implementation, not interface) changes to force more files to be recompiled.
– user79758
Jan 5 '11 at 22:42
14
@Joe: Yes, and there's still no noticeable cost. C++ uses templates, that's just something we all have to understand, accept, and get over.
– GManNickG
Jan 5 '11 at 22:54
36
Wait, what's this "copysign is slow" business...? Using current compilers (g++ 4.6+, clang++ 3.0),std::copysign
seems to result in excellent code for me: 4 instructions (inlined), no branching, entirely using the FPU. The recipe given in this answer, by contrast, generates much worse code (many more instructions, including a multiply, moving back and forth between integer unit and FPU)...
– snogglethorpe
Jan 23 '12 at 6:35
13
@snogglethorpe: If you're callingcopysign
on an int it promotes to float/double, and must narrow again on return. Your compiler may optimize that promotion out but I can't find anything suggesting that's guaranteed by the standard. Also to implement signum via copysign you need to manually handle the 0 case - please make sure you include that in any performance comparison.
– user79758
Jan 23 '12 at 9:31
42
The first version is not branchless. Why do people think that a comparison used in an expression will not generate a branch? It will on most architectures. Only processors that have a cmove (or predication) will generate branchless code, but they'll do it also for ternaries or if/else if it is a win.
– Patrick Schlüter
Mar 12 '12 at 15:41
|
show 18 more comments
16
@GMan: GCC only just now (4.5) stopped having cost quadratic to the number of instantiations for template functions, and they are still drastically more expensive to parse and instantiate than manually written functions or the standard C preprocessor. The linker also has to do more work to remove duplicate instantiations. Templates also encourage #includes-in-#includes, which makes dependency calculation take longer and small (often implementation, not interface) changes to force more files to be recompiled.
– user79758
Jan 5 '11 at 22:42
14
@Joe: Yes, and there's still no noticeable cost. C++ uses templates, that's just something we all have to understand, accept, and get over.
– GManNickG
Jan 5 '11 at 22:54
36
Wait, what's this "copysign is slow" business...? Using current compilers (g++ 4.6+, clang++ 3.0),std::copysign
seems to result in excellent code for me: 4 instructions (inlined), no branching, entirely using the FPU. The recipe given in this answer, by contrast, generates much worse code (many more instructions, including a multiply, moving back and forth between integer unit and FPU)...
– snogglethorpe
Jan 23 '12 at 6:35
13
@snogglethorpe: If you're callingcopysign
on an int it promotes to float/double, and must narrow again on return. Your compiler may optimize that promotion out but I can't find anything suggesting that's guaranteed by the standard. Also to implement signum via copysign you need to manually handle the 0 case - please make sure you include that in any performance comparison.
– user79758
Jan 23 '12 at 9:31
42
The first version is not branchless. Why do people think that a comparison used in an expression will not generate a branch? It will on most architectures. Only processors that have a cmove (or predication) will generate branchless code, but they'll do it also for ternaries or if/else if it is a win.
– Patrick Schlüter
Mar 12 '12 at 15:41
16
16
@GMan: GCC only just now (4.5) stopped having cost quadratic to the number of instantiations for template functions, and they are still drastically more expensive to parse and instantiate than manually written functions or the standard C preprocessor. The linker also has to do more work to remove duplicate instantiations. Templates also encourage #includes-in-#includes, which makes dependency calculation take longer and small (often implementation, not interface) changes to force more files to be recompiled.
– user79758
Jan 5 '11 at 22:42
@GMan: GCC only just now (4.5) stopped having cost quadratic to the number of instantiations for template functions, and they are still drastically more expensive to parse and instantiate than manually written functions or the standard C preprocessor. The linker also has to do more work to remove duplicate instantiations. Templates also encourage #includes-in-#includes, which makes dependency calculation take longer and small (often implementation, not interface) changes to force more files to be recompiled.
– user79758
Jan 5 '11 at 22:42
14
14
@Joe: Yes, and there's still no noticeable cost. C++ uses templates, that's just something we all have to understand, accept, and get over.
– GManNickG
Jan 5 '11 at 22:54
@Joe: Yes, and there's still no noticeable cost. C++ uses templates, that's just something we all have to understand, accept, and get over.
– GManNickG
Jan 5 '11 at 22:54
36
36
Wait, what's this "copysign is slow" business...? Using current compilers (g++ 4.6+, clang++ 3.0),
std::copysign
seems to result in excellent code for me: 4 instructions (inlined), no branching, entirely using the FPU. The recipe given in this answer, by contrast, generates much worse code (many more instructions, including a multiply, moving back and forth between integer unit and FPU)...– snogglethorpe
Jan 23 '12 at 6:35
Wait, what's this "copysign is slow" business...? Using current compilers (g++ 4.6+, clang++ 3.0),
std::copysign
seems to result in excellent code for me: 4 instructions (inlined), no branching, entirely using the FPU. The recipe given in this answer, by contrast, generates much worse code (many more instructions, including a multiply, moving back and forth between integer unit and FPU)...– snogglethorpe
Jan 23 '12 at 6:35
13
13
@snogglethorpe: If you're calling
copysign
on an int it promotes to float/double, and must narrow again on return. Your compiler may optimize that promotion out but I can't find anything suggesting that's guaranteed by the standard. Also to implement signum via copysign you need to manually handle the 0 case - please make sure you include that in any performance comparison.– user79758
Jan 23 '12 at 9:31
@snogglethorpe: If you're calling
copysign
on an int it promotes to float/double, and must narrow again on return. Your compiler may optimize that promotion out but I can't find anything suggesting that's guaranteed by the standard. Also to implement signum via copysign you need to manually handle the 0 case - please make sure you include that in any performance comparison.– user79758
Jan 23 '12 at 9:31
42
42
The first version is not branchless. Why do people think that a comparison used in an expression will not generate a branch? It will on most architectures. Only processors that have a cmove (or predication) will generate branchless code, but they'll do it also for ternaries or if/else if it is a win.
– Patrick Schlüter
Mar 12 '12 at 15:41
The first version is not branchless. Why do people think that a comparison used in an expression will not generate a branch? It will on most architectures. Only processors that have a cmove (or predication) will generate branchless code, but they'll do it also for ternaries or if/else if it is a win.
– Patrick Schlüter
Mar 12 '12 at 15:41
|
show 18 more comments
I don't know of a standard function for it. Here's an interesting way to write it though:
(x > 0) - (x < 0)
Here's a more readable way to do it:
if (x > 0) return 1;
if (x < 0) return -1;
return 0;
If you like the ternary operator you can do this:
(x > 0) ? 1 : ((x < 0) ? -1 : 0)
6
Also one that works without branches. Nice.
– Joey
Dec 14 '09 at 22:31
6
Mark Ransom, your expressions give incorrect results forx==0
.
– avakar
Dec 14 '09 at 22:45
10
@Svante: not exactly. A value of0
is "false"; any other value is "true"; however, the relational and equality operators always return0
or1
(see Standard 6.5.8 and 6.5.9). -- the value of the expressiona * (x == 42)
is either0
ora
.
– pmg
Dec 14 '09 at 23:21
21
High-Performance Mark, I'm amazed that you missed the C++ tag. This answer is very much valid and doesn't deserve a down-vote. Moreover, I wouldn't usecopysign
for integralx
even if I had it available.
– avakar
Dec 15 '09 at 8:39
4
Has anyone actually checked what code GCC/G++/any other compiler emits on a real platform? My guess is that the "branchless" version uses two branches instead of one. Bitshifting is probably a lot faster - and more portable in terms of performance.
– Jørgen Fogh
Sep 2 '11 at 11:29
|
show 18 more comments
I don't know of a standard function for it. Here's an interesting way to write it though:
(x > 0) - (x < 0)
Here's a more readable way to do it:
if (x > 0) return 1;
if (x < 0) return -1;
return 0;
If you like the ternary operator you can do this:
(x > 0) ? 1 : ((x < 0) ? -1 : 0)
6
Also one that works without branches. Nice.
– Joey
Dec 14 '09 at 22:31
6
Mark Ransom, your expressions give incorrect results forx==0
.
– avakar
Dec 14 '09 at 22:45
10
@Svante: not exactly. A value of0
is "false"; any other value is "true"; however, the relational and equality operators always return0
or1
(see Standard 6.5.8 and 6.5.9). -- the value of the expressiona * (x == 42)
is either0
ora
.
– pmg
Dec 14 '09 at 23:21
21
High-Performance Mark, I'm amazed that you missed the C++ tag. This answer is very much valid and doesn't deserve a down-vote. Moreover, I wouldn't usecopysign
for integralx
even if I had it available.
– avakar
Dec 15 '09 at 8:39
4
Has anyone actually checked what code GCC/G++/any other compiler emits on a real platform? My guess is that the "branchless" version uses two branches instead of one. Bitshifting is probably a lot faster - and more portable in terms of performance.
– Jørgen Fogh
Sep 2 '11 at 11:29
|
show 18 more comments
I don't know of a standard function for it. Here's an interesting way to write it though:
(x > 0) - (x < 0)
Here's a more readable way to do it:
if (x > 0) return 1;
if (x < 0) return -1;
return 0;
If you like the ternary operator you can do this:
(x > 0) ? 1 : ((x < 0) ? -1 : 0)
I don't know of a standard function for it. Here's an interesting way to write it though:
(x > 0) - (x < 0)
Here's a more readable way to do it:
if (x > 0) return 1;
if (x < 0) return -1;
return 0;
If you like the ternary operator you can do this:
(x > 0) ? 1 : ((x < 0) ? -1 : 0)
edited Dec 15 '09 at 8:19
answered Dec 14 '09 at 22:30
Mark ByersMark Byers
588k12513491338
588k12513491338
6
Also one that works without branches. Nice.
– Joey
Dec 14 '09 at 22:31
6
Mark Ransom, your expressions give incorrect results forx==0
.
– avakar
Dec 14 '09 at 22:45
10
@Svante: not exactly. A value of0
is "false"; any other value is "true"; however, the relational and equality operators always return0
or1
(see Standard 6.5.8 and 6.5.9). -- the value of the expressiona * (x == 42)
is either0
ora
.
– pmg
Dec 14 '09 at 23:21
21
High-Performance Mark, I'm amazed that you missed the C++ tag. This answer is very much valid and doesn't deserve a down-vote. Moreover, I wouldn't usecopysign
for integralx
even if I had it available.
– avakar
Dec 15 '09 at 8:39
4
Has anyone actually checked what code GCC/G++/any other compiler emits on a real platform? My guess is that the "branchless" version uses two branches instead of one. Bitshifting is probably a lot faster - and more portable in terms of performance.
– Jørgen Fogh
Sep 2 '11 at 11:29
|
show 18 more comments
6
Also one that works without branches. Nice.
– Joey
Dec 14 '09 at 22:31
6
Mark Ransom, your expressions give incorrect results forx==0
.
– avakar
Dec 14 '09 at 22:45
10
@Svante: not exactly. A value of0
is "false"; any other value is "true"; however, the relational and equality operators always return0
or1
(see Standard 6.5.8 and 6.5.9). -- the value of the expressiona * (x == 42)
is either0
ora
.
– pmg
Dec 14 '09 at 23:21
21
High-Performance Mark, I'm amazed that you missed the C++ tag. This answer is very much valid and doesn't deserve a down-vote. Moreover, I wouldn't usecopysign
for integralx
even if I had it available.
– avakar
Dec 15 '09 at 8:39
4
Has anyone actually checked what code GCC/G++/any other compiler emits on a real platform? My guess is that the "branchless" version uses two branches instead of one. Bitshifting is probably a lot faster - and more portable in terms of performance.
– Jørgen Fogh
Sep 2 '11 at 11:29
6
6
Also one that works without branches. Nice.
– Joey
Dec 14 '09 at 22:31
Also one that works without branches. Nice.
– Joey
Dec 14 '09 at 22:31
6
6
Mark Ransom, your expressions give incorrect results for
x==0
.– avakar
Dec 14 '09 at 22:45
Mark Ransom, your expressions give incorrect results for
x==0
.– avakar
Dec 14 '09 at 22:45
10
10
@Svante: not exactly. A value of
0
is "false"; any other value is "true"; however, the relational and equality operators always return 0
or 1
(see Standard 6.5.8 and 6.5.9). -- the value of the expression a * (x == 42)
is either 0
or a
.– pmg
Dec 14 '09 at 23:21
@Svante: not exactly. A value of
0
is "false"; any other value is "true"; however, the relational and equality operators always return 0
or 1
(see Standard 6.5.8 and 6.5.9). -- the value of the expression a * (x == 42)
is either 0
or a
.– pmg
Dec 14 '09 at 23:21
21
21
High-Performance Mark, I'm amazed that you missed the C++ tag. This answer is very much valid and doesn't deserve a down-vote. Moreover, I wouldn't use
copysign
for integral x
even if I had it available.– avakar
Dec 15 '09 at 8:39
High-Performance Mark, I'm amazed that you missed the C++ tag. This answer is very much valid and doesn't deserve a down-vote. Moreover, I wouldn't use
copysign
for integral x
even if I had it available.– avakar
Dec 15 '09 at 8:39
4
4
Has anyone actually checked what code GCC/G++/any other compiler emits on a real platform? My guess is that the "branchless" version uses two branches instead of one. Bitshifting is probably a lot faster - and more portable in terms of performance.
– Jørgen Fogh
Sep 2 '11 at 11:29
Has anyone actually checked what code GCC/G++/any other compiler emits on a real platform? My guess is that the "branchless" version uses two branches instead of one. Bitshifting is probably a lot faster - and more portable in terms of performance.
– Jørgen Fogh
Sep 2 '11 at 11:29
|
show 18 more comments
There is a C99 math library function called copysign(), which takes the sign from one argument and the absolute value from the other:
result = copysign(1.0, value) // double
result = copysignf(1.0, value) // float
result = copysignl(1.0, value) // long double
will give you a result of +/- 1.0, depending on the sign of value. Note that floating point zeroes are signed: (+0) will yield +1, and (-0) will yield -1.
51
Upvoted this one, downvoted most popular answer. Left reeling in amazement that SO community seems to prefer a hack to use of a standard library function. May the gods of programming condemn you all to trying to decipher hacks used by clever programmers unfamiliar with language standards. Yeah, I know this is going to cost me a ton of rep on SO, but I'd rather side with comingstorm than the rest of you ...
– High Performance Mark
Dec 15 '09 at 7:42
26
This is close, but it gives the wrong answer for zero (according to the Wikipedia article in the question at least). Nice suggestion though. +1 anyway.
– Mark Byers
Dec 15 '09 at 8:25
4
If you want an integer, or if you want the exact signum result for zeros, I like Mark Byers' answer, which is fiendishly elegant! If you don't care about the above, copysign() might have a performance advanage, depending on the application -- if I were optimizing a critical loop, I would try both.
– comingstorm
Dec 16 '09 at 10:08
10
1) C99 is not fully supported everywhere (consider VC++); 2) this is also a C++ question. This is a good answer, but the upvoted one also works, and is more widely applicable.
– Pavel Minaev
Dec 31 '09 at 9:17
5
Savior! Needed a way to determine between -0.0 and 0.0
– Ólafur Waage
May 14 '11 at 13:32
|
show 4 more comments
There is a C99 math library function called copysign(), which takes the sign from one argument and the absolute value from the other:
result = copysign(1.0, value) // double
result = copysignf(1.0, value) // float
result = copysignl(1.0, value) // long double
will give you a result of +/- 1.0, depending on the sign of value. Note that floating point zeroes are signed: (+0) will yield +1, and (-0) will yield -1.
51
Upvoted this one, downvoted most popular answer. Left reeling in amazement that SO community seems to prefer a hack to use of a standard library function. May the gods of programming condemn you all to trying to decipher hacks used by clever programmers unfamiliar with language standards. Yeah, I know this is going to cost me a ton of rep on SO, but I'd rather side with comingstorm than the rest of you ...
– High Performance Mark
Dec 15 '09 at 7:42
26
This is close, but it gives the wrong answer for zero (according to the Wikipedia article in the question at least). Nice suggestion though. +1 anyway.
– Mark Byers
Dec 15 '09 at 8:25
4
If you want an integer, or if you want the exact signum result for zeros, I like Mark Byers' answer, which is fiendishly elegant! If you don't care about the above, copysign() might have a performance advanage, depending on the application -- if I were optimizing a critical loop, I would try both.
– comingstorm
Dec 16 '09 at 10:08
10
1) C99 is not fully supported everywhere (consider VC++); 2) this is also a C++ question. This is a good answer, but the upvoted one also works, and is more widely applicable.
– Pavel Minaev
Dec 31 '09 at 9:17
5
Savior! Needed a way to determine between -0.0 and 0.0
– Ólafur Waage
May 14 '11 at 13:32
|
show 4 more comments
There is a C99 math library function called copysign(), which takes the sign from one argument and the absolute value from the other:
result = copysign(1.0, value) // double
result = copysignf(1.0, value) // float
result = copysignl(1.0, value) // long double
will give you a result of +/- 1.0, depending on the sign of value. Note that floating point zeroes are signed: (+0) will yield +1, and (-0) will yield -1.
There is a C99 math library function called copysign(), which takes the sign from one argument and the absolute value from the other:
result = copysign(1.0, value) // double
result = copysignf(1.0, value) // float
result = copysignl(1.0, value) // long double
will give you a result of +/- 1.0, depending on the sign of value. Note that floating point zeroes are signed: (+0) will yield +1, and (-0) will yield -1.
edited Oct 4 '11 at 1:38
answered Dec 15 '09 at 4:19
comingstormcomingstorm
19.9k12956
19.9k12956
51
Upvoted this one, downvoted most popular answer. Left reeling in amazement that SO community seems to prefer a hack to use of a standard library function. May the gods of programming condemn you all to trying to decipher hacks used by clever programmers unfamiliar with language standards. Yeah, I know this is going to cost me a ton of rep on SO, but I'd rather side with comingstorm than the rest of you ...
– High Performance Mark
Dec 15 '09 at 7:42
26
This is close, but it gives the wrong answer for zero (according to the Wikipedia article in the question at least). Nice suggestion though. +1 anyway.
– Mark Byers
Dec 15 '09 at 8:25
4
If you want an integer, or if you want the exact signum result for zeros, I like Mark Byers' answer, which is fiendishly elegant! If you don't care about the above, copysign() might have a performance advanage, depending on the application -- if I were optimizing a critical loop, I would try both.
– comingstorm
Dec 16 '09 at 10:08
10
1) C99 is not fully supported everywhere (consider VC++); 2) this is also a C++ question. This is a good answer, but the upvoted one also works, and is more widely applicable.
– Pavel Minaev
Dec 31 '09 at 9:17
5
Savior! Needed a way to determine between -0.0 and 0.0
– Ólafur Waage
May 14 '11 at 13:32
|
show 4 more comments
51
Upvoted this one, downvoted most popular answer. Left reeling in amazement that SO community seems to prefer a hack to use of a standard library function. May the gods of programming condemn you all to trying to decipher hacks used by clever programmers unfamiliar with language standards. Yeah, I know this is going to cost me a ton of rep on SO, but I'd rather side with comingstorm than the rest of you ...
– High Performance Mark
Dec 15 '09 at 7:42
26
This is close, but it gives the wrong answer for zero (according to the Wikipedia article in the question at least). Nice suggestion though. +1 anyway.
– Mark Byers
Dec 15 '09 at 8:25
4
If you want an integer, or if you want the exact signum result for zeros, I like Mark Byers' answer, which is fiendishly elegant! If you don't care about the above, copysign() might have a performance advanage, depending on the application -- if I were optimizing a critical loop, I would try both.
– comingstorm
Dec 16 '09 at 10:08
10
1) C99 is not fully supported everywhere (consider VC++); 2) this is also a C++ question. This is a good answer, but the upvoted one also works, and is more widely applicable.
– Pavel Minaev
Dec 31 '09 at 9:17
5
Savior! Needed a way to determine between -0.0 and 0.0
– Ólafur Waage
May 14 '11 at 13:32
51
51
Upvoted this one, downvoted most popular answer. Left reeling in amazement that SO community seems to prefer a hack to use of a standard library function. May the gods of programming condemn you all to trying to decipher hacks used by clever programmers unfamiliar with language standards. Yeah, I know this is going to cost me a ton of rep on SO, but I'd rather side with comingstorm than the rest of you ...
– High Performance Mark
Dec 15 '09 at 7:42
Upvoted this one, downvoted most popular answer. Left reeling in amazement that SO community seems to prefer a hack to use of a standard library function. May the gods of programming condemn you all to trying to decipher hacks used by clever programmers unfamiliar with language standards. Yeah, I know this is going to cost me a ton of rep on SO, but I'd rather side with comingstorm than the rest of you ...
– High Performance Mark
Dec 15 '09 at 7:42
26
26
This is close, but it gives the wrong answer for zero (according to the Wikipedia article in the question at least). Nice suggestion though. +1 anyway.
– Mark Byers
Dec 15 '09 at 8:25
This is close, but it gives the wrong answer for zero (according to the Wikipedia article in the question at least). Nice suggestion though. +1 anyway.
– Mark Byers
Dec 15 '09 at 8:25
4
4
If you want an integer, or if you want the exact signum result for zeros, I like Mark Byers' answer, which is fiendishly elegant! If you don't care about the above, copysign() might have a performance advanage, depending on the application -- if I were optimizing a critical loop, I would try both.
– comingstorm
Dec 16 '09 at 10:08
If you want an integer, or if you want the exact signum result for zeros, I like Mark Byers' answer, which is fiendishly elegant! If you don't care about the above, copysign() might have a performance advanage, depending on the application -- if I were optimizing a critical loop, I would try both.
– comingstorm
Dec 16 '09 at 10:08
10
10
1) C99 is not fully supported everywhere (consider VC++); 2) this is also a C++ question. This is a good answer, but the upvoted one also works, and is more widely applicable.
– Pavel Minaev
Dec 31 '09 at 9:17
1) C99 is not fully supported everywhere (consider VC++); 2) this is also a C++ question. This is a good answer, but the upvoted one also works, and is more widely applicable.
– Pavel Minaev
Dec 31 '09 at 9:17
5
5
Savior! Needed a way to determine between -0.0 and 0.0
– Ólafur Waage
May 14 '11 at 13:32
Savior! Needed a way to determine between -0.0 and 0.0
– Ólafur Waage
May 14 '11 at 13:32
|
show 4 more comments
Apparently, the answer to the original poster's question is no. There is no standard C++ sgn
function.
2
Actually there is one : en.cppreference.com/w/cpp/numeric/math/copysign. Use : std::copysign(1, x); Note that the return type is not integral.
– SR_
Nov 14 '17 at 12:15
add a comment |
Apparently, the answer to the original poster's question is no. There is no standard C++ sgn
function.
2
Actually there is one : en.cppreference.com/w/cpp/numeric/math/copysign. Use : std::copysign(1, x); Note that the return type is not integral.
– SR_
Nov 14 '17 at 12:15
add a comment |
Apparently, the answer to the original poster's question is no. There is no standard C++ sgn
function.
Apparently, the answer to the original poster's question is no. There is no standard C++ sgn
function.
answered Apr 13 '12 at 0:24
JohnJohn
4,02023755
4,02023755
2
Actually there is one : en.cppreference.com/w/cpp/numeric/math/copysign. Use : std::copysign(1, x); Note that the return type is not integral.
– SR_
Nov 14 '17 at 12:15
add a comment |
2
Actually there is one : en.cppreference.com/w/cpp/numeric/math/copysign. Use : std::copysign(1, x); Note that the return type is not integral.
– SR_
Nov 14 '17 at 12:15
2
2
Actually there is one : en.cppreference.com/w/cpp/numeric/math/copysign. Use : std::copysign(1, x); Note that the return type is not integral.
– SR_
Nov 14 '17 at 12:15
Actually there is one : en.cppreference.com/w/cpp/numeric/math/copysign. Use : std::copysign(1, x); Note that the return type is not integral.
– SR_
Nov 14 '17 at 12:15
add a comment |
It seems that most of the answers missed the original question.
Is there a standard sign function (signum, sgn) in C/C++?
Not in the standard library, but there is in boost
, which might as well be part of the standard.
#include <boost/math/special_functions/sign.hpp>
//Returns 1 if x > 0, -1 if x < 0, and 0 if x is zero.
template <class T>
inline int sign (const T& z);
http://www.boost.org/doc/libs/1_47_0/libs/math/doc/sf_and_dist/html/math_toolkit/utils/sign_functions.html
4
This should be the most top-voted answer, as it gives the closest possible solution to what's asked in the question.
– BartoszKP
Mar 20 '15 at 14:20
I have been wondering for the past few minutes why the standard library doesn't have sign function. It is just so common -- definitely more commonly used than gamma function which could be found in cmath header.
– Taozi
Feb 22 '16 at 22:33
3
The explanation I often get for similar questions is "it's easy enough to implement yourself" Which IMO is not a good reason. It completely belies the problems of where standardization, unobvious edge cases, and where to put such a widely used tool.
– Catskul
Feb 22 '16 at 22:35
add a comment |
It seems that most of the answers missed the original question.
Is there a standard sign function (signum, sgn) in C/C++?
Not in the standard library, but there is in boost
, which might as well be part of the standard.
#include <boost/math/special_functions/sign.hpp>
//Returns 1 if x > 0, -1 if x < 0, and 0 if x is zero.
template <class T>
inline int sign (const T& z);
http://www.boost.org/doc/libs/1_47_0/libs/math/doc/sf_and_dist/html/math_toolkit/utils/sign_functions.html
4
This should be the most top-voted answer, as it gives the closest possible solution to what's asked in the question.
– BartoszKP
Mar 20 '15 at 14:20
I have been wondering for the past few minutes why the standard library doesn't have sign function. It is just so common -- definitely more commonly used than gamma function which could be found in cmath header.
– Taozi
Feb 22 '16 at 22:33
3
The explanation I often get for similar questions is "it's easy enough to implement yourself" Which IMO is not a good reason. It completely belies the problems of where standardization, unobvious edge cases, and where to put such a widely used tool.
– Catskul
Feb 22 '16 at 22:35
add a comment |
It seems that most of the answers missed the original question.
Is there a standard sign function (signum, sgn) in C/C++?
Not in the standard library, but there is in boost
, which might as well be part of the standard.
#include <boost/math/special_functions/sign.hpp>
//Returns 1 if x > 0, -1 if x < 0, and 0 if x is zero.
template <class T>
inline int sign (const T& z);
http://www.boost.org/doc/libs/1_47_0/libs/math/doc/sf_and_dist/html/math_toolkit/utils/sign_functions.html
It seems that most of the answers missed the original question.
Is there a standard sign function (signum, sgn) in C/C++?
Not in the standard library, but there is in boost
, which might as well be part of the standard.
#include <boost/math/special_functions/sign.hpp>
//Returns 1 if x > 0, -1 if x < 0, and 0 if x is zero.
template <class T>
inline int sign (const T& z);
http://www.boost.org/doc/libs/1_47_0/libs/math/doc/sf_and_dist/html/math_toolkit/utils/sign_functions.html
answered Jun 1 '13 at 4:23
CatskulCatskul
8,00296398
8,00296398
4
This should be the most top-voted answer, as it gives the closest possible solution to what's asked in the question.
– BartoszKP
Mar 20 '15 at 14:20
I have been wondering for the past few minutes why the standard library doesn't have sign function. It is just so common -- definitely more commonly used than gamma function which could be found in cmath header.
– Taozi
Feb 22 '16 at 22:33
3
The explanation I often get for similar questions is "it's easy enough to implement yourself" Which IMO is not a good reason. It completely belies the problems of where standardization, unobvious edge cases, and where to put such a widely used tool.
– Catskul
Feb 22 '16 at 22:35
add a comment |
4
This should be the most top-voted answer, as it gives the closest possible solution to what's asked in the question.
– BartoszKP
Mar 20 '15 at 14:20
I have been wondering for the past few minutes why the standard library doesn't have sign function. It is just so common -- definitely more commonly used than gamma function which could be found in cmath header.
– Taozi
Feb 22 '16 at 22:33
3
The explanation I often get for similar questions is "it's easy enough to implement yourself" Which IMO is not a good reason. It completely belies the problems of where standardization, unobvious edge cases, and where to put such a widely used tool.
– Catskul
Feb 22 '16 at 22:35
4
4
This should be the most top-voted answer, as it gives the closest possible solution to what's asked in the question.
– BartoszKP
Mar 20 '15 at 14:20
This should be the most top-voted answer, as it gives the closest possible solution to what's asked in the question.
– BartoszKP
Mar 20 '15 at 14:20
I have been wondering for the past few minutes why the standard library doesn't have sign function. It is just so common -- definitely more commonly used than gamma function which could be found in cmath header.
– Taozi
Feb 22 '16 at 22:33
I have been wondering for the past few minutes why the standard library doesn't have sign function. It is just so common -- definitely more commonly used than gamma function which could be found in cmath header.
– Taozi
Feb 22 '16 at 22:33
3
3
The explanation I often get for similar questions is "it's easy enough to implement yourself" Which IMO is not a good reason. It completely belies the problems of where standardization, unobvious edge cases, and where to put such a widely used tool.
– Catskul
Feb 22 '16 at 22:35
The explanation I often get for similar questions is "it's easy enough to implement yourself" Which IMO is not a good reason. It completely belies the problems of where standardization, unobvious edge cases, and where to put such a widely used tool.
– Catskul
Feb 22 '16 at 22:35
add a comment |
Faster than the above solutions, including the highest rated one:
(x < 0) ? -1 : (x > 0)
What type is x? Or are you using a #define?
– Chance
Feb 20 '12 at 18:11
3
Your type is not faster. It will cause a cache miss quite often.
– Jeffrey Drake
Dec 30 '12 at 3:19
16
Cache miss? I'm not sure how. Perhaps you meant branch misprediction?
– Catskul
Jun 1 '13 at 5:10
1
It seems to me this will result in a warning of confusing integer and boolean types!
– sergiol
Sep 2 '15 at 11:55
how this will be fast with the branch?
– Nick
Jul 15 '17 at 19:55
add a comment |
Faster than the above solutions, including the highest rated one:
(x < 0) ? -1 : (x > 0)
What type is x? Or are you using a #define?
– Chance
Feb 20 '12 at 18:11
3
Your type is not faster. It will cause a cache miss quite often.
– Jeffrey Drake
Dec 30 '12 at 3:19
16
Cache miss? I'm not sure how. Perhaps you meant branch misprediction?
– Catskul
Jun 1 '13 at 5:10
1
It seems to me this will result in a warning of confusing integer and boolean types!
– sergiol
Sep 2 '15 at 11:55
how this will be fast with the branch?
– Nick
Jul 15 '17 at 19:55
add a comment |
Faster than the above solutions, including the highest rated one:
(x < 0) ? -1 : (x > 0)
Faster than the above solutions, including the highest rated one:
(x < 0) ? -1 : (x > 0)
edited Oct 11 '12 at 0:02
Tim Cooper
119k32239226
119k32239226
answered Aug 17 '11 at 20:10
xnxxnx
38337
38337
What type is x? Or are you using a #define?
– Chance
Feb 20 '12 at 18:11
3
Your type is not faster. It will cause a cache miss quite often.
– Jeffrey Drake
Dec 30 '12 at 3:19
16
Cache miss? I'm not sure how. Perhaps you meant branch misprediction?
– Catskul
Jun 1 '13 at 5:10
1
It seems to me this will result in a warning of confusing integer and boolean types!
– sergiol
Sep 2 '15 at 11:55
how this will be fast with the branch?
– Nick
Jul 15 '17 at 19:55
add a comment |
What type is x? Or are you using a #define?
– Chance
Feb 20 '12 at 18:11
3
Your type is not faster. It will cause a cache miss quite often.
– Jeffrey Drake
Dec 30 '12 at 3:19
16
Cache miss? I'm not sure how. Perhaps you meant branch misprediction?
– Catskul
Jun 1 '13 at 5:10
1
It seems to me this will result in a warning of confusing integer and boolean types!
– sergiol
Sep 2 '15 at 11:55
how this will be fast with the branch?
– Nick
Jul 15 '17 at 19:55
What type is x? Or are you using a #define?
– Chance
Feb 20 '12 at 18:11
What type is x? Or are you using a #define?
– Chance
Feb 20 '12 at 18:11
3
3
Your type is not faster. It will cause a cache miss quite often.
– Jeffrey Drake
Dec 30 '12 at 3:19
Your type is not faster. It will cause a cache miss quite often.
– Jeffrey Drake
Dec 30 '12 at 3:19
16
16
Cache miss? I'm not sure how. Perhaps you meant branch misprediction?
– Catskul
Jun 1 '13 at 5:10
Cache miss? I'm not sure how. Perhaps you meant branch misprediction?
– Catskul
Jun 1 '13 at 5:10
1
1
It seems to me this will result in a warning of confusing integer and boolean types!
– sergiol
Sep 2 '15 at 11:55
It seems to me this will result in a warning of confusing integer and boolean types!
– sergiol
Sep 2 '15 at 11:55
how this will be fast with the branch?
– Nick
Jul 15 '17 at 19:55
how this will be fast with the branch?
– Nick
Jul 15 '17 at 19:55
add a comment |
Is there a standard sign function (signum, sgn) in C/C++?
Yes, depending on definition.
C99 and later has the signbit()
macro in <math.h>
int signbit
(real-floatingx
);
Thesignbit
macro returns a nonzero value if and only if the sign of its argument value is negative. C11 §7.12.3.6
Yet OP wants something a little different.
I want a function that returns -1 for negative numbers and +1 for positive numbers. ... a function working on floats.
#define signbit_p1_or_n1(x) ((signbit(x) ? -1 : 1)
Deeper:
The post is not specific in the following cases, x = 0.0, -0.0, +NaN, -NaN
.
A classic signum()
returns +1
on x>0
, -1
on x>0
and 0
on x==0
.
Many answers have already covered that, but do not address x = -0.0, +NaN, -NaN
. Many are geared for an integer point-of-view that usually lacks Not-a-Numbers (NaN) and -0.0.
Typical answers function like signnum_typical()
On -0.0, +NaN, -NaN
, they return 0.0, 0.0, 0.0
.
int signnum_typical(double x) {
if (x > 0.0) return 1;
if (x < 0.0) return -1;
return 0;
}
Instead, propose this functionality: On -0.0, +NaN, -NaN
, it returns -0.0, +NaN, -NaN
.
double signnum_c(double x) {
if (x > 0.0) return 1.0;
if (x < 0.0) return -1.0;
return x;
}
1
Ah, exactly what I'm after. This just changed in Pharo Smalltalk github.com/pharo-project/pharo/pull/1835 and I wondered if there was some sort of standard (IEC 60559 or ISO 10967) dictating behavior for negative zero and nan behaviour... I like the javascript sign developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
– aka.nice
Sep 30 '18 at 19:27
add a comment |
Is there a standard sign function (signum, sgn) in C/C++?
Yes, depending on definition.
C99 and later has the signbit()
macro in <math.h>
int signbit
(real-floatingx
);
Thesignbit
macro returns a nonzero value if and only if the sign of its argument value is negative. C11 §7.12.3.6
Yet OP wants something a little different.
I want a function that returns -1 for negative numbers and +1 for positive numbers. ... a function working on floats.
#define signbit_p1_or_n1(x) ((signbit(x) ? -1 : 1)
Deeper:
The post is not specific in the following cases, x = 0.0, -0.0, +NaN, -NaN
.
A classic signum()
returns +1
on x>0
, -1
on x>0
and 0
on x==0
.
Many answers have already covered that, but do not address x = -0.0, +NaN, -NaN
. Many are geared for an integer point-of-view that usually lacks Not-a-Numbers (NaN) and -0.0.
Typical answers function like signnum_typical()
On -0.0, +NaN, -NaN
, they return 0.0, 0.0, 0.0
.
int signnum_typical(double x) {
if (x > 0.0) return 1;
if (x < 0.0) return -1;
return 0;
}
Instead, propose this functionality: On -0.0, +NaN, -NaN
, it returns -0.0, +NaN, -NaN
.
double signnum_c(double x) {
if (x > 0.0) return 1.0;
if (x < 0.0) return -1.0;
return x;
}
1
Ah, exactly what I'm after. This just changed in Pharo Smalltalk github.com/pharo-project/pharo/pull/1835 and I wondered if there was some sort of standard (IEC 60559 or ISO 10967) dictating behavior for negative zero and nan behaviour... I like the javascript sign developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
– aka.nice
Sep 30 '18 at 19:27
add a comment |
Is there a standard sign function (signum, sgn) in C/C++?
Yes, depending on definition.
C99 and later has the signbit()
macro in <math.h>
int signbit
(real-floatingx
);
Thesignbit
macro returns a nonzero value if and only if the sign of its argument value is negative. C11 §7.12.3.6
Yet OP wants something a little different.
I want a function that returns -1 for negative numbers and +1 for positive numbers. ... a function working on floats.
#define signbit_p1_or_n1(x) ((signbit(x) ? -1 : 1)
Deeper:
The post is not specific in the following cases, x = 0.0, -0.0, +NaN, -NaN
.
A classic signum()
returns +1
on x>0
, -1
on x>0
and 0
on x==0
.
Many answers have already covered that, but do not address x = -0.0, +NaN, -NaN
. Many are geared for an integer point-of-view that usually lacks Not-a-Numbers (NaN) and -0.0.
Typical answers function like signnum_typical()
On -0.0, +NaN, -NaN
, they return 0.0, 0.0, 0.0
.
int signnum_typical(double x) {
if (x > 0.0) return 1;
if (x < 0.0) return -1;
return 0;
}
Instead, propose this functionality: On -0.0, +NaN, -NaN
, it returns -0.0, +NaN, -NaN
.
double signnum_c(double x) {
if (x > 0.0) return 1.0;
if (x < 0.0) return -1.0;
return x;
}
Is there a standard sign function (signum, sgn) in C/C++?
Yes, depending on definition.
C99 and later has the signbit()
macro in <math.h>
int signbit
(real-floatingx
);
Thesignbit
macro returns a nonzero value if and only if the sign of its argument value is negative. C11 §7.12.3.6
Yet OP wants something a little different.
I want a function that returns -1 for negative numbers and +1 for positive numbers. ... a function working on floats.
#define signbit_p1_or_n1(x) ((signbit(x) ? -1 : 1)
Deeper:
The post is not specific in the following cases, x = 0.0, -0.0, +NaN, -NaN
.
A classic signum()
returns +1
on x>0
, -1
on x>0
and 0
on x==0
.
Many answers have already covered that, but do not address x = -0.0, +NaN, -NaN
. Many are geared for an integer point-of-view that usually lacks Not-a-Numbers (NaN) and -0.0.
Typical answers function like signnum_typical()
On -0.0, +NaN, -NaN
, they return 0.0, 0.0, 0.0
.
int signnum_typical(double x) {
if (x > 0.0) return 1;
if (x < 0.0) return -1;
return 0;
}
Instead, propose this functionality: On -0.0, +NaN, -NaN
, it returns -0.0, +NaN, -NaN
.
double signnum_c(double x) {
if (x > 0.0) return 1.0;
if (x < 0.0) return -1.0;
return x;
}
answered Feb 18 '16 at 20:24
chuxchux
82.3k872148
82.3k872148
1
Ah, exactly what I'm after. This just changed in Pharo Smalltalk github.com/pharo-project/pharo/pull/1835 and I wondered if there was some sort of standard (IEC 60559 or ISO 10967) dictating behavior for negative zero and nan behaviour... I like the javascript sign developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
– aka.nice
Sep 30 '18 at 19:27
add a comment |
1
Ah, exactly what I'm after. This just changed in Pharo Smalltalk github.com/pharo-project/pharo/pull/1835 and I wondered if there was some sort of standard (IEC 60559 or ISO 10967) dictating behavior for negative zero and nan behaviour... I like the javascript sign developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
– aka.nice
Sep 30 '18 at 19:27
1
1
Ah, exactly what I'm after. This just changed in Pharo Smalltalk github.com/pharo-project/pharo/pull/1835 and I wondered if there was some sort of standard (IEC 60559 or ISO 10967) dictating behavior for negative zero and nan behaviour... I like the javascript sign developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
– aka.nice
Sep 30 '18 at 19:27
Ah, exactly what I'm after. This just changed in Pharo Smalltalk github.com/pharo-project/pharo/pull/1835 and I wondered if there was some sort of standard (IEC 60559 or ISO 10967) dictating behavior for negative zero and nan behaviour... I like the javascript sign developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
– aka.nice
Sep 30 '18 at 19:27
add a comment |
There's a way to do it without branching, but it's not very pretty.
sign = -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
http://graphics.stanford.edu/~seander/bithacks.html
Lots of other interesting, overly-clever stuff on that page, too...
1
If I read the link correctly that only returns -1 or 0. If you want -1, 0, or +1 then it'ssign = (v != 0) | -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
orsign = (v > 0) - (v < 0);
.
– Z boson
Apr 21 '15 at 7:58
1
Not exactly what we call portable code...
– flederwiesel
Dec 1 '16 at 18:18
add a comment |
There's a way to do it without branching, but it's not very pretty.
sign = -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
http://graphics.stanford.edu/~seander/bithacks.html
Lots of other interesting, overly-clever stuff on that page, too...
1
If I read the link correctly that only returns -1 or 0. If you want -1, 0, or +1 then it'ssign = (v != 0) | -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
orsign = (v > 0) - (v < 0);
.
– Z boson
Apr 21 '15 at 7:58
1
Not exactly what we call portable code...
– flederwiesel
Dec 1 '16 at 18:18
add a comment |
There's a way to do it without branching, but it's not very pretty.
sign = -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
http://graphics.stanford.edu/~seander/bithacks.html
Lots of other interesting, overly-clever stuff on that page, too...
There's a way to do it without branching, but it's not very pretty.
sign = -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
http://graphics.stanford.edu/~seander/bithacks.html
Lots of other interesting, overly-clever stuff on that page, too...
answered Dec 14 '09 at 22:52
Tim SylvesterTim Sylvester
20.1k26584
20.1k26584
1
If I read the link correctly that only returns -1 or 0. If you want -1, 0, or +1 then it'ssign = (v != 0) | -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
orsign = (v > 0) - (v < 0);
.
– Z boson
Apr 21 '15 at 7:58
1
Not exactly what we call portable code...
– flederwiesel
Dec 1 '16 at 18:18
add a comment |
1
If I read the link correctly that only returns -1 or 0. If you want -1, 0, or +1 then it'ssign = (v != 0) | -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
orsign = (v > 0) - (v < 0);
.
– Z boson
Apr 21 '15 at 7:58
1
Not exactly what we call portable code...
– flederwiesel
Dec 1 '16 at 18:18
1
1
If I read the link correctly that only returns -1 or 0. If you want -1, 0, or +1 then it's
sign = (v != 0) | -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
or sign = (v > 0) - (v < 0);
.– Z boson
Apr 21 '15 at 7:58
If I read the link correctly that only returns -1 or 0. If you want -1, 0, or +1 then it's
sign = (v != 0) | -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
or sign = (v > 0) - (v < 0);
.– Z boson
Apr 21 '15 at 7:58
1
1
Not exactly what we call portable code...
– flederwiesel
Dec 1 '16 at 18:18
Not exactly what we call portable code...
– flederwiesel
Dec 1 '16 at 18:18
add a comment |
If all you want is to test the sign, use signbit (returns true if its argument has a negative sign).
Not sure why you would particularly want -1 or +1 returned; copysign is more convenient
for that, but it sounds like it will return +1 for negative zero on some platforms with
only partial support for negative zero, where signbit presumably would return true.
5
There's many mathematical applications in which the sign(x) is necessary. Otherwise I'd just doif (x < 0)
.
– Chance
Mar 9 '12 at 16:42
add a comment |
If all you want is to test the sign, use signbit (returns true if its argument has a negative sign).
Not sure why you would particularly want -1 or +1 returned; copysign is more convenient
for that, but it sounds like it will return +1 for negative zero on some platforms with
only partial support for negative zero, where signbit presumably would return true.
5
There's many mathematical applications in which the sign(x) is necessary. Otherwise I'd just doif (x < 0)
.
– Chance
Mar 9 '12 at 16:42
add a comment |
If all you want is to test the sign, use signbit (returns true if its argument has a negative sign).
Not sure why you would particularly want -1 or +1 returned; copysign is more convenient
for that, but it sounds like it will return +1 for negative zero on some platforms with
only partial support for negative zero, where signbit presumably would return true.
If all you want is to test the sign, use signbit (returns true if its argument has a negative sign).
Not sure why you would particularly want -1 or +1 returned; copysign is more convenient
for that, but it sounds like it will return +1 for negative zero on some platforms with
only partial support for negative zero, where signbit presumably would return true.
edited Jan 4 '10 at 3:16
answered Dec 15 '09 at 5:59
ysthysth
78.1k494191
78.1k494191
5
There's many mathematical applications in which the sign(x) is necessary. Otherwise I'd just doif (x < 0)
.
– Chance
Mar 9 '12 at 16:42
add a comment |
5
There's many mathematical applications in which the sign(x) is necessary. Otherwise I'd just doif (x < 0)
.
– Chance
Mar 9 '12 at 16:42
5
5
There's many mathematical applications in which the sign(x) is necessary. Otherwise I'd just do
if (x < 0)
.– Chance
Mar 9 '12 at 16:42
There's many mathematical applications in which the sign(x) is necessary. Otherwise I'd just do
if (x < 0)
.– Chance
Mar 9 '12 at 16:42
add a comment |
In general, there is no standard signum function in C/C++, and the lack of such a fundamental function tells you a lot about these languages.
Apart from that, I believe both majority viewpoints about the right approach to define such a function are in a way correct, and the "controversy" about it is actually a non-argument once you take into account two important caveats:
A signum function should always return the type of its operand, similarly to an
abs()
function, because signum is usually used for multiplication with an absolute value after the latter has been processed somehow. Therefore, the major use case of signum is not comparisons but arithmetic, and the latter shouldn't involve any expensive integer-to/from-floating-point conversions.Floating point types do not feature a single exact zero value: +0.0 can be interpreted as "infinitesimally above zero", and -0.0 as "infinitesimally below zero". That's the reason why comparisons involving zero must internally check against both values, and an expression like
x == 0.0
can be dangerous.
Regarding C, I think the best way forward with integral types is indeed to use the (x > 0) - (x < 0)
expression, as it should be translated in a branch-free fashion, and requires only three basic operations. Best define inline functions that enforce a return type matching the argument type, and add a C11 define _Generic
to map these functions to a common name.
With floating point values, I think inline functions based on C11 copysignf(1.0f, x)
, copysign(1.0, x)
, and copysignl(1.0l, x)
are the way to go, simply because they're also highly likely to be branch-free, and additionally do not require casting the result from integer back into a floating point value. You should probably comment prominently that your floating point implementations of signum will not return zero because of the peculiarities of floating point zero values, processing time considerations, and also because it is often very useful in floating point arithmetic to receive the correct -1/+1 sign, even for zero values.
add a comment |
In general, there is no standard signum function in C/C++, and the lack of such a fundamental function tells you a lot about these languages.
Apart from that, I believe both majority viewpoints about the right approach to define such a function are in a way correct, and the "controversy" about it is actually a non-argument once you take into account two important caveats:
A signum function should always return the type of its operand, similarly to an
abs()
function, because signum is usually used for multiplication with an absolute value after the latter has been processed somehow. Therefore, the major use case of signum is not comparisons but arithmetic, and the latter shouldn't involve any expensive integer-to/from-floating-point conversions.Floating point types do not feature a single exact zero value: +0.0 can be interpreted as "infinitesimally above zero", and -0.0 as "infinitesimally below zero". That's the reason why comparisons involving zero must internally check against both values, and an expression like
x == 0.0
can be dangerous.
Regarding C, I think the best way forward with integral types is indeed to use the (x > 0) - (x < 0)
expression, as it should be translated in a branch-free fashion, and requires only three basic operations. Best define inline functions that enforce a return type matching the argument type, and add a C11 define _Generic
to map these functions to a common name.
With floating point values, I think inline functions based on C11 copysignf(1.0f, x)
, copysign(1.0, x)
, and copysignl(1.0l, x)
are the way to go, simply because they're also highly likely to be branch-free, and additionally do not require casting the result from integer back into a floating point value. You should probably comment prominently that your floating point implementations of signum will not return zero because of the peculiarities of floating point zero values, processing time considerations, and also because it is often very useful in floating point arithmetic to receive the correct -1/+1 sign, even for zero values.
add a comment |
In general, there is no standard signum function in C/C++, and the lack of such a fundamental function tells you a lot about these languages.
Apart from that, I believe both majority viewpoints about the right approach to define such a function are in a way correct, and the "controversy" about it is actually a non-argument once you take into account two important caveats:
A signum function should always return the type of its operand, similarly to an
abs()
function, because signum is usually used for multiplication with an absolute value after the latter has been processed somehow. Therefore, the major use case of signum is not comparisons but arithmetic, and the latter shouldn't involve any expensive integer-to/from-floating-point conversions.Floating point types do not feature a single exact zero value: +0.0 can be interpreted as "infinitesimally above zero", and -0.0 as "infinitesimally below zero". That's the reason why comparisons involving zero must internally check against both values, and an expression like
x == 0.0
can be dangerous.
Regarding C, I think the best way forward with integral types is indeed to use the (x > 0) - (x < 0)
expression, as it should be translated in a branch-free fashion, and requires only three basic operations. Best define inline functions that enforce a return type matching the argument type, and add a C11 define _Generic
to map these functions to a common name.
With floating point values, I think inline functions based on C11 copysignf(1.0f, x)
, copysign(1.0, x)
, and copysignl(1.0l, x)
are the way to go, simply because they're also highly likely to be branch-free, and additionally do not require casting the result from integer back into a floating point value. You should probably comment prominently that your floating point implementations of signum will not return zero because of the peculiarities of floating point zero values, processing time considerations, and also because it is often very useful in floating point arithmetic to receive the correct -1/+1 sign, even for zero values.
In general, there is no standard signum function in C/C++, and the lack of such a fundamental function tells you a lot about these languages.
Apart from that, I believe both majority viewpoints about the right approach to define such a function are in a way correct, and the "controversy" about it is actually a non-argument once you take into account two important caveats:
A signum function should always return the type of its operand, similarly to an
abs()
function, because signum is usually used for multiplication with an absolute value after the latter has been processed somehow. Therefore, the major use case of signum is not comparisons but arithmetic, and the latter shouldn't involve any expensive integer-to/from-floating-point conversions.Floating point types do not feature a single exact zero value: +0.0 can be interpreted as "infinitesimally above zero", and -0.0 as "infinitesimally below zero". That's the reason why comparisons involving zero must internally check against both values, and an expression like
x == 0.0
can be dangerous.
Regarding C, I think the best way forward with integral types is indeed to use the (x > 0) - (x < 0)
expression, as it should be translated in a branch-free fashion, and requires only three basic operations. Best define inline functions that enforce a return type matching the argument type, and add a C11 define _Generic
to map these functions to a common name.
With floating point values, I think inline functions based on C11 copysignf(1.0f, x)
, copysign(1.0, x)
, and copysignl(1.0l, x)
are the way to go, simply because they're also highly likely to be branch-free, and additionally do not require casting the result from integer back into a floating point value. You should probably comment prominently that your floating point implementations of signum will not return zero because of the peculiarities of floating point zero values, processing time considerations, and also because it is often very useful in floating point arithmetic to receive the correct -1/+1 sign, even for zero values.
edited May 26 '15 at 13:07
seh
13.2k3853
13.2k3853
answered May 26 '15 at 3:05
TabernakelTabernakel
6113
6113
add a comment |
add a comment |
My copy of C in a Nutshell reveals the existence of a standard function called copysign which might be useful. It looks as if copysign(1.0, -2.0) would return -1.0 and copysign(1.0, 2.0) would return +1.0.
Pretty close huh?
Not standard, but may be widely available. Microsoft's starts with an underscore, which is the convention they use for non-standard extensions. Not the best choice when you're working with integers, though.
– Mark Ransom
Dec 14 '09 at 23:33
5
copysign is both in the ISO C (C99) and POSIX standards. See opengroup.org/onlinepubs/000095399/functions/copysign.html
– lhf
Dec 15 '09 at 1:19
3
What lhf said. Visual Studio is not a reference for the C standard.
– Stephen Canon
Dec 15 '09 at 1:42
add a comment |
My copy of C in a Nutshell reveals the existence of a standard function called copysign which might be useful. It looks as if copysign(1.0, -2.0) would return -1.0 and copysign(1.0, 2.0) would return +1.0.
Pretty close huh?
Not standard, but may be widely available. Microsoft's starts with an underscore, which is the convention they use for non-standard extensions. Not the best choice when you're working with integers, though.
– Mark Ransom
Dec 14 '09 at 23:33
5
copysign is both in the ISO C (C99) and POSIX standards. See opengroup.org/onlinepubs/000095399/functions/copysign.html
– lhf
Dec 15 '09 at 1:19
3
What lhf said. Visual Studio is not a reference for the C standard.
– Stephen Canon
Dec 15 '09 at 1:42
add a comment |
My copy of C in a Nutshell reveals the existence of a standard function called copysign which might be useful. It looks as if copysign(1.0, -2.0) would return -1.0 and copysign(1.0, 2.0) would return +1.0.
Pretty close huh?
My copy of C in a Nutshell reveals the existence of a standard function called copysign which might be useful. It looks as if copysign(1.0, -2.0) would return -1.0 and copysign(1.0, 2.0) would return +1.0.
Pretty close huh?
edited Jan 22 '16 at 18:53
mbaitoff
4,70641731
4,70641731
answered Dec 14 '09 at 23:15
High Performance MarkHigh Performance Mark
68.8k783134
68.8k783134
Not standard, but may be widely available. Microsoft's starts with an underscore, which is the convention they use for non-standard extensions. Not the best choice when you're working with integers, though.
– Mark Ransom
Dec 14 '09 at 23:33
5
copysign is both in the ISO C (C99) and POSIX standards. See opengroup.org/onlinepubs/000095399/functions/copysign.html
– lhf
Dec 15 '09 at 1:19
3
What lhf said. Visual Studio is not a reference for the C standard.
– Stephen Canon
Dec 15 '09 at 1:42
add a comment |
Not standard, but may be widely available. Microsoft's starts with an underscore, which is the convention they use for non-standard extensions. Not the best choice when you're working with integers, though.
– Mark Ransom
Dec 14 '09 at 23:33
5
copysign is both in the ISO C (C99) and POSIX standards. See opengroup.org/onlinepubs/000095399/functions/copysign.html
– lhf
Dec 15 '09 at 1:19
3
What lhf said. Visual Studio is not a reference for the C standard.
– Stephen Canon
Dec 15 '09 at 1:42
Not standard, but may be widely available. Microsoft's starts with an underscore, which is the convention they use for non-standard extensions. Not the best choice when you're working with integers, though.
– Mark Ransom
Dec 14 '09 at 23:33
Not standard, but may be widely available. Microsoft's starts with an underscore, which is the convention they use for non-standard extensions. Not the best choice when you're working with integers, though.
– Mark Ransom
Dec 14 '09 at 23:33
5
5
copysign is both in the ISO C (C99) and POSIX standards. See opengroup.org/onlinepubs/000095399/functions/copysign.html
– lhf
Dec 15 '09 at 1:19
copysign is both in the ISO C (C99) and POSIX standards. See opengroup.org/onlinepubs/000095399/functions/copysign.html
– lhf
Dec 15 '09 at 1:19
3
3
What lhf said. Visual Studio is not a reference for the C standard.
– Stephen Canon
Dec 15 '09 at 1:42
What lhf said. Visual Studio is not a reference for the C standard.
– Stephen Canon
Dec 15 '09 at 1:42
add a comment |
No, it doesn't exist in c++, like in matlab. I use a macro in my programs for this.
#define sign(a) ( ( (a) < 0 ) ? -1 : ( (a) > 0 ) )
4
One should prefer templates over macros in C++.
– Ruslan
Jan 27 '16 at 11:06
In C, there is no template ...... helloacm.com/how-to-implement-the-sgn-function-in-c
– justyy
Oct 20 '16 at 10:55
I thought this was a good answer then I looked at my own code and found this:#define sign(x) (((x) > 0) - ((x) < 0))
which is good too.
– Michel Rouzic
Feb 25 '18 at 12:12
1
an inline function is better than a macro in C, and in C++ template is better
– phuclv
Apr 10 '18 at 16:05
add a comment |
No, it doesn't exist in c++, like in matlab. I use a macro in my programs for this.
#define sign(a) ( ( (a) < 0 ) ? -1 : ( (a) > 0 ) )
4
One should prefer templates over macros in C++.
– Ruslan
Jan 27 '16 at 11:06
In C, there is no template ...... helloacm.com/how-to-implement-the-sgn-function-in-c
– justyy
Oct 20 '16 at 10:55
I thought this was a good answer then I looked at my own code and found this:#define sign(x) (((x) > 0) - ((x) < 0))
which is good too.
– Michel Rouzic
Feb 25 '18 at 12:12
1
an inline function is better than a macro in C, and in C++ template is better
– phuclv
Apr 10 '18 at 16:05
add a comment |
No, it doesn't exist in c++, like in matlab. I use a macro in my programs for this.
#define sign(a) ( ( (a) < 0 ) ? -1 : ( (a) > 0 ) )
No, it doesn't exist in c++, like in matlab. I use a macro in my programs for this.
#define sign(a) ( ( (a) < 0 ) ? -1 : ( (a) > 0 ) )
answered Jul 10 '14 at 23:35
chatteringchattering
631
631
4
One should prefer templates over macros in C++.
– Ruslan
Jan 27 '16 at 11:06
In C, there is no template ...... helloacm.com/how-to-implement-the-sgn-function-in-c
– justyy
Oct 20 '16 at 10:55
I thought this was a good answer then I looked at my own code and found this:#define sign(x) (((x) > 0) - ((x) < 0))
which is good too.
– Michel Rouzic
Feb 25 '18 at 12:12
1
an inline function is better than a macro in C, and in C++ template is better
– phuclv
Apr 10 '18 at 16:05
add a comment |
4
One should prefer templates over macros in C++.
– Ruslan
Jan 27 '16 at 11:06
In C, there is no template ...... helloacm.com/how-to-implement-the-sgn-function-in-c
– justyy
Oct 20 '16 at 10:55
I thought this was a good answer then I looked at my own code and found this:#define sign(x) (((x) > 0) - ((x) < 0))
which is good too.
– Michel Rouzic
Feb 25 '18 at 12:12
1
an inline function is better than a macro in C, and in C++ template is better
– phuclv
Apr 10 '18 at 16:05
4
4
One should prefer templates over macros in C++.
– Ruslan
Jan 27 '16 at 11:06
One should prefer templates over macros in C++.
– Ruslan
Jan 27 '16 at 11:06
In C, there is no template ...... helloacm.com/how-to-implement-the-sgn-function-in-c
– justyy
Oct 20 '16 at 10:55
In C, there is no template ...... helloacm.com/how-to-implement-the-sgn-function-in-c
– justyy
Oct 20 '16 at 10:55
I thought this was a good answer then I looked at my own code and found this:
#define sign(x) (((x) > 0) - ((x) < 0))
which is good too.– Michel Rouzic
Feb 25 '18 at 12:12
I thought this was a good answer then I looked at my own code and found this:
#define sign(x) (((x) > 0) - ((x) < 0))
which is good too.– Michel Rouzic
Feb 25 '18 at 12:12
1
1
an inline function is better than a macro in C, and in C++ template is better
– phuclv
Apr 10 '18 at 16:05
an inline function is better than a macro in C, and in C++ template is better
– phuclv
Apr 10 '18 at 16:05
add a comment |
The accepted Answer with the overload below does indeed not trigger -Wtype-limits however it triggers -Wunused-parameter on the is_signed
argument.
template <typename T> inline constexpr
int signum(T x, std::false_type is_signed) {
return T(0) < x;
}
template <typename T> inline constexpr
int signum(T x, std::true_type is_signed) {
return (T(0) < x) - (x < T(0));
}
template <typename T> inline constexpr
int signum(T x) {
return signum(x, std::is_signed<T>());
}
For C++11 an alternative could be.
template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, int>::type
inline constexpr signum(T x) {
return T(0) < x;
}
template <typename T>
typename std::enable_if<std::is_signed<T>::value, int>::type
inline constexpr signum(T x) {
return (T(0) < x) - (x < T(0));
}
For me it does not trigger any warnings on GCC 5.3.1
To avoid the-Wunused-parameter
warning just use unnamed parameters.
– Jonathan Wakely
Jan 24 at 12:47
That is actually very true. I missed that. However, I like the C++11 alternative more either way.
– SamVanDonut
yesterday
add a comment |
The accepted Answer with the overload below does indeed not trigger -Wtype-limits however it triggers -Wunused-parameter on the is_signed
argument.
template <typename T> inline constexpr
int signum(T x, std::false_type is_signed) {
return T(0) < x;
}
template <typename T> inline constexpr
int signum(T x, std::true_type is_signed) {
return (T(0) < x) - (x < T(0));
}
template <typename T> inline constexpr
int signum(T x) {
return signum(x, std::is_signed<T>());
}
For C++11 an alternative could be.
template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, int>::type
inline constexpr signum(T x) {
return T(0) < x;
}
template <typename T>
typename std::enable_if<std::is_signed<T>::value, int>::type
inline constexpr signum(T x) {
return (T(0) < x) - (x < T(0));
}
For me it does not trigger any warnings on GCC 5.3.1
To avoid the-Wunused-parameter
warning just use unnamed parameters.
– Jonathan Wakely
Jan 24 at 12:47
That is actually very true. I missed that. However, I like the C++11 alternative more either way.
– SamVanDonut
yesterday
add a comment |
The accepted Answer with the overload below does indeed not trigger -Wtype-limits however it triggers -Wunused-parameter on the is_signed
argument.
template <typename T> inline constexpr
int signum(T x, std::false_type is_signed) {
return T(0) < x;
}
template <typename T> inline constexpr
int signum(T x, std::true_type is_signed) {
return (T(0) < x) - (x < T(0));
}
template <typename T> inline constexpr
int signum(T x) {
return signum(x, std::is_signed<T>());
}
For C++11 an alternative could be.
template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, int>::type
inline constexpr signum(T x) {
return T(0) < x;
}
template <typename T>
typename std::enable_if<std::is_signed<T>::value, int>::type
inline constexpr signum(T x) {
return (T(0) < x) - (x < T(0));
}
For me it does not trigger any warnings on GCC 5.3.1
The accepted Answer with the overload below does indeed not trigger -Wtype-limits however it triggers -Wunused-parameter on the is_signed
argument.
template <typename T> inline constexpr
int signum(T x, std::false_type is_signed) {
return T(0) < x;
}
template <typename T> inline constexpr
int signum(T x, std::true_type is_signed) {
return (T(0) < x) - (x < T(0));
}
template <typename T> inline constexpr
int signum(T x) {
return signum(x, std::is_signed<T>());
}
For C++11 an alternative could be.
template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, int>::type
inline constexpr signum(T x) {
return T(0) < x;
}
template <typename T>
typename std::enable_if<std::is_signed<T>::value, int>::type
inline constexpr signum(T x) {
return (T(0) < x) - (x < T(0));
}
For me it does not trigger any warnings on GCC 5.3.1
edited Jan 13 '17 at 17:14
answered Jan 13 '17 at 15:59
SamVanDonutSamVanDonut
9219
9219
To avoid the-Wunused-parameter
warning just use unnamed parameters.
– Jonathan Wakely
Jan 24 at 12:47
That is actually very true. I missed that. However, I like the C++11 alternative more either way.
– SamVanDonut
yesterday
add a comment |
To avoid the-Wunused-parameter
warning just use unnamed parameters.
– Jonathan Wakely
Jan 24 at 12:47
That is actually very true. I missed that. However, I like the C++11 alternative more either way.
– SamVanDonut
yesterday
To avoid the
-Wunused-parameter
warning just use unnamed parameters.– Jonathan Wakely
Jan 24 at 12:47
To avoid the
-Wunused-parameter
warning just use unnamed parameters.– Jonathan Wakely
Jan 24 at 12:47
That is actually very true. I missed that. However, I like the C++11 alternative more either way.
– SamVanDonut
yesterday
That is actually very true. I missed that. However, I like the C++11 alternative more either way.
– SamVanDonut
yesterday
add a comment |
Bit off-topic, but I use this:
template<typename T>
constexpr int sgn(const T &a, const T &b) noexcept{
return (a > b) - (a < b);
}
template<typename T>
constexpr int sgn(const T &a) noexcept{
return sgn(a, T(0));
}
and I found first function - the one with two arguments, to be much more useful from "standard" sgn(), because it is most often used in code like this:
int comp(unsigned a, unsigned b){
return sgn( int(a) - int(b) );
}
vs.
int comp(unsigned a, unsigned b){
return sgn(a, b);
}
there is no cast for unsigned types and no additional minus.
in fact i have this piece of code using sgn()
template <class T>
int comp(const T &a, const T &b){
log__("all");
if (a < b)
return -1;
if (a > b)
return +1;
return 0;
}
inline int comp(int const a, int const b){
log__("int");
return a - b;
}
inline int comp(long int const a, long int const b){
log__("long");
return sgn(a, b);
}
add a comment |
Bit off-topic, but I use this:
template<typename T>
constexpr int sgn(const T &a, const T &b) noexcept{
return (a > b) - (a < b);
}
template<typename T>
constexpr int sgn(const T &a) noexcept{
return sgn(a, T(0));
}
and I found first function - the one with two arguments, to be much more useful from "standard" sgn(), because it is most often used in code like this:
int comp(unsigned a, unsigned b){
return sgn( int(a) - int(b) );
}
vs.
int comp(unsigned a, unsigned b){
return sgn(a, b);
}
there is no cast for unsigned types and no additional minus.
in fact i have this piece of code using sgn()
template <class T>
int comp(const T &a, const T &b){
log__("all");
if (a < b)
return -1;
if (a > b)
return +1;
return 0;
}
inline int comp(int const a, int const b){
log__("int");
return a - b;
}
inline int comp(long int const a, long int const b){
log__("long");
return sgn(a, b);
}
add a comment |
Bit off-topic, but I use this:
template<typename T>
constexpr int sgn(const T &a, const T &b) noexcept{
return (a > b) - (a < b);
}
template<typename T>
constexpr int sgn(const T &a) noexcept{
return sgn(a, T(0));
}
and I found first function - the one with two arguments, to be much more useful from "standard" sgn(), because it is most often used in code like this:
int comp(unsigned a, unsigned b){
return sgn( int(a) - int(b) );
}
vs.
int comp(unsigned a, unsigned b){
return sgn(a, b);
}
there is no cast for unsigned types and no additional minus.
in fact i have this piece of code using sgn()
template <class T>
int comp(const T &a, const T &b){
log__("all");
if (a < b)
return -1;
if (a > b)
return +1;
return 0;
}
inline int comp(int const a, int const b){
log__("int");
return a - b;
}
inline int comp(long int const a, long int const b){
log__("long");
return sgn(a, b);
}
Bit off-topic, but I use this:
template<typename T>
constexpr int sgn(const T &a, const T &b) noexcept{
return (a > b) - (a < b);
}
template<typename T>
constexpr int sgn(const T &a) noexcept{
return sgn(a, T(0));
}
and I found first function - the one with two arguments, to be much more useful from "standard" sgn(), because it is most often used in code like this:
int comp(unsigned a, unsigned b){
return sgn( int(a) - int(b) );
}
vs.
int comp(unsigned a, unsigned b){
return sgn(a, b);
}
there is no cast for unsigned types and no additional minus.
in fact i have this piece of code using sgn()
template <class T>
int comp(const T &a, const T &b){
log__("all");
if (a < b)
return -1;
if (a > b)
return +1;
return 0;
}
inline int comp(int const a, int const b){
log__("int");
return a - b;
}
inline int comp(long int const a, long int const b){
log__("long");
return sgn(a, b);
}
answered Jul 15 '17 at 20:03
NickNick
4,43212647
4,43212647
add a comment |
add a comment |
You can use boost::math::sign()
method from boost/math/special_functions/sign.hpp
if boost is available.
Note that this was suggested before: stackoverflow.com/a/16869019/1187415.
– Martin R
Aug 29 '18 at 8:41
add a comment |
You can use boost::math::sign()
method from boost/math/special_functions/sign.hpp
if boost is available.
Note that this was suggested before: stackoverflow.com/a/16869019/1187415.
– Martin R
Aug 29 '18 at 8:41
add a comment |
You can use boost::math::sign()
method from boost/math/special_functions/sign.hpp
if boost is available.
You can use boost::math::sign()
method from boost/math/special_functions/sign.hpp
if boost is available.
answered Aug 29 '18 at 7:58
khkarenskhkarens
5801514
5801514
Note that this was suggested before: stackoverflow.com/a/16869019/1187415.
– Martin R
Aug 29 '18 at 8:41
add a comment |
Note that this was suggested before: stackoverflow.com/a/16869019/1187415.
– Martin R
Aug 29 '18 at 8:41
Note that this was suggested before: stackoverflow.com/a/16869019/1187415.
– Martin R
Aug 29 '18 at 8:41
Note that this was suggested before: stackoverflow.com/a/16869019/1187415.
– Martin R
Aug 29 '18 at 8:41
add a comment |
int sign(float n)
{
union { float f; std::uint32_t i; } u { n };
return 1 - ((u.i >> 31) << 1);
}
This function assumes:
binary32 representation of floating point numbers- a compiler that make an exception about the strict aliasing rule when using a named union
3
There are still some bad assumptions here. For example I don't believe the endianness of the float is guaranteed to be the endianness of the integer. Your check also fails on any architectures using ILP64. Really, you're just reimplementingcopysign
; if you're usingstatic_assert
you've got C++11, and might as well really usecopysign
.
– user79758
Mar 15 '12 at 18:24
add a comment |
int sign(float n)
{
union { float f; std::uint32_t i; } u { n };
return 1 - ((u.i >> 31) << 1);
}
This function assumes:
binary32 representation of floating point numbers- a compiler that make an exception about the strict aliasing rule when using a named union
3
There are still some bad assumptions here. For example I don't believe the endianness of the float is guaranteed to be the endianness of the integer. Your check also fails on any architectures using ILP64. Really, you're just reimplementingcopysign
; if you're usingstatic_assert
you've got C++11, and might as well really usecopysign
.
– user79758
Mar 15 '12 at 18:24
add a comment |
int sign(float n)
{
union { float f; std::uint32_t i; } u { n };
return 1 - ((u.i >> 31) << 1);
}
This function assumes:
binary32 representation of floating point numbers- a compiler that make an exception about the strict aliasing rule when using a named union
int sign(float n)
{
union { float f; std::uint32_t i; } u { n };
return 1 - ((u.i >> 31) << 1);
}
This function assumes:
binary32 representation of floating point numbers- a compiler that make an exception about the strict aliasing rule when using a named union
edited Aug 14 '12 at 19:12
answered Feb 3 '12 at 1:04
GigiGigi
4,1422023
4,1422023
3
There are still some bad assumptions here. For example I don't believe the endianness of the float is guaranteed to be the endianness of the integer. Your check also fails on any architectures using ILP64. Really, you're just reimplementingcopysign
; if you're usingstatic_assert
you've got C++11, and might as well really usecopysign
.
– user79758
Mar 15 '12 at 18:24
add a comment |
3
There are still some bad assumptions here. For example I don't believe the endianness of the float is guaranteed to be the endianness of the integer. Your check also fails on any architectures using ILP64. Really, you're just reimplementingcopysign
; if you're usingstatic_assert
you've got C++11, and might as well really usecopysign
.
– user79758
Mar 15 '12 at 18:24
3
3
There are still some bad assumptions here. For example I don't believe the endianness of the float is guaranteed to be the endianness of the integer. Your check also fails on any architectures using ILP64. Really, you're just reimplementing
copysign
; if you're using static_assert
you've got C++11, and might as well really use copysign
.– user79758
Mar 15 '12 at 18:24
There are still some bad assumptions here. For example I don't believe the endianness of the float is guaranteed to be the endianness of the integer. Your check also fails on any architectures using ILP64. Really, you're just reimplementing
copysign
; if you're using static_assert
you've got C++11, and might as well really use copysign
.– user79758
Mar 15 '12 at 18:24
add a comment |
While the integer solution in the accepted answer is quite elegant it bothered me that it wouldn't be able to return NAN for double types, so I modified it slightly.
template <typename T> double sgn(T val) {
return double((T(0) < val) - (val < T(0)))/(val == val);
}
Note that returning a floating point NAN as opposed to a hard coded NAN
causes the sign bit to be set in some implementations, so the output for val = -NAN
and val = NAN
are going to be identical no matter what (if you prefer a "nan
" output over a -nan
you can put an abs(val)
before the return...)
add a comment |
While the integer solution in the accepted answer is quite elegant it bothered me that it wouldn't be able to return NAN for double types, so I modified it slightly.
template <typename T> double sgn(T val) {
return double((T(0) < val) - (val < T(0)))/(val == val);
}
Note that returning a floating point NAN as opposed to a hard coded NAN
causes the sign bit to be set in some implementations, so the output for val = -NAN
and val = NAN
are going to be identical no matter what (if you prefer a "nan
" output over a -nan
you can put an abs(val)
before the return...)
add a comment |
While the integer solution in the accepted answer is quite elegant it bothered me that it wouldn't be able to return NAN for double types, so I modified it slightly.
template <typename T> double sgn(T val) {
return double((T(0) < val) - (val < T(0)))/(val == val);
}
Note that returning a floating point NAN as opposed to a hard coded NAN
causes the sign bit to be set in some implementations, so the output for val = -NAN
and val = NAN
are going to be identical no matter what (if you prefer a "nan
" output over a -nan
you can put an abs(val)
before the return...)
While the integer solution in the accepted answer is quite elegant it bothered me that it wouldn't be able to return NAN for double types, so I modified it slightly.
template <typename T> double sgn(T val) {
return double((T(0) < val) - (val < T(0)))/(val == val);
}
Note that returning a floating point NAN as opposed to a hard coded NAN
causes the sign bit to be set in some implementations, so the output for val = -NAN
and val = NAN
are going to be identical no matter what (if you prefer a "nan
" output over a -nan
you can put an abs(val)
before the return...)
answered Aug 11 '17 at 8:19
mrclngmrclng
1267
1267
add a comment |
add a comment |
Here's a branching-friendly implementation:
inline int signum(const double x) {
if(x == 0) return 0;
return (1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}
Unless your data has zeros as half of the numbers, here the branch predictor will choose one of the branches as the most common. Both branches only involve simple operations.
Alternatively, on some compilers and CPU architectures a completely branchless version may be faster:
inline int signum(const double x) {
return (x != 0) *
(1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}
This works for IEEE 754 double-precision binary floating-point format: binary64 .
add a comment |
Here's a branching-friendly implementation:
inline int signum(const double x) {
if(x == 0) return 0;
return (1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}
Unless your data has zeros as half of the numbers, here the branch predictor will choose one of the branches as the most common. Both branches only involve simple operations.
Alternatively, on some compilers and CPU architectures a completely branchless version may be faster:
inline int signum(const double x) {
return (x != 0) *
(1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}
This works for IEEE 754 double-precision binary floating-point format: binary64 .
add a comment |
Here's a branching-friendly implementation:
inline int signum(const double x) {
if(x == 0) return 0;
return (1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}
Unless your data has zeros as half of the numbers, here the branch predictor will choose one of the branches as the most common. Both branches only involve simple operations.
Alternatively, on some compilers and CPU architectures a completely branchless version may be faster:
inline int signum(const double x) {
return (x != 0) *
(1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}
This works for IEEE 754 double-precision binary floating-point format: binary64 .
Here's a branching-friendly implementation:
inline int signum(const double x) {
if(x == 0) return 0;
return (1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}
Unless your data has zeros as half of the numbers, here the branch predictor will choose one of the branches as the most common. Both branches only involve simple operations.
Alternatively, on some compilers and CPU architectures a completely branchless version may be faster:
inline int signum(const double x) {
return (x != 0) *
(1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}
This works for IEEE 754 double-precision binary floating-point format: binary64 .
edited Nov 19 '18 at 11:41
answered Nov 19 '18 at 9:29
Serge RogatchSerge Rogatch
6,14623364
6,14623364
add a comment |
add a comment |
Why use ternary operators and if-else when you can simply do this
#define sgn(x) x==0 ? 0 : x/abs(x)
1
Your definition uses a ternary operator as well.
– Martin R
Jun 30 '18 at 14:26
Yes Definitely, but it just uses one ternary operator to separate zero and non-zero numbers. Others' versions include nested ternary ops to separate positive, negative and zero.
– Jagreet
Jun 30 '18 at 16:15
add a comment |
Why use ternary operators and if-else when you can simply do this
#define sgn(x) x==0 ? 0 : x/abs(x)
1
Your definition uses a ternary operator as well.
– Martin R
Jun 30 '18 at 14:26
Yes Definitely, but it just uses one ternary operator to separate zero and non-zero numbers. Others' versions include nested ternary ops to separate positive, negative and zero.
– Jagreet
Jun 30 '18 at 16:15
add a comment |
Why use ternary operators and if-else when you can simply do this
#define sgn(x) x==0 ? 0 : x/abs(x)
Why use ternary operators and if-else when you can simply do this
#define sgn(x) x==0 ? 0 : x/abs(x)
answered Jun 30 '18 at 1:29
JagreetJagreet
6319
6319
1
Your definition uses a ternary operator as well.
– Martin R
Jun 30 '18 at 14:26
Yes Definitely, but it just uses one ternary operator to separate zero and non-zero numbers. Others' versions include nested ternary ops to separate positive, negative and zero.
– Jagreet
Jun 30 '18 at 16:15
add a comment |
1
Your definition uses a ternary operator as well.
– Martin R
Jun 30 '18 at 14:26
Yes Definitely, but it just uses one ternary operator to separate zero and non-zero numbers. Others' versions include nested ternary ops to separate positive, negative and zero.
– Jagreet
Jun 30 '18 at 16:15
1
1
Your definition uses a ternary operator as well.
– Martin R
Jun 30 '18 at 14:26
Your definition uses a ternary operator as well.
– Martin R
Jun 30 '18 at 14:26
Yes Definitely, but it just uses one ternary operator to separate zero and non-zero numbers. Others' versions include nested ternary ops to separate positive, negative and zero.
– Jagreet
Jun 30 '18 at 16:15
Yes Definitely, but it just uses one ternary operator to separate zero and non-zero numbers. Others' versions include nested ternary ops to separate positive, negative and zero.
– Jagreet
Jun 30 '18 at 16:15
add a comment |
double signof(double a) { return (a == 0) ? 0 : (a<0 ? -1 : 1); }
add a comment |
double signof(double a) { return (a == 0) ? 0 : (a<0 ? -1 : 1); }
add a comment |
double signof(double a) { return (a == 0) ? 0 : (a<0 ? -1 : 1); }
double signof(double a) { return (a == 0) ? 0 : (a<0 ? -1 : 1); }
edited Nov 4 '12 at 16:05
arrowd
22.2k44981
22.2k44981
answered Nov 4 '12 at 15:46
cyberioncyberion
283
283
add a comment |
add a comment |
I ran into this just today. So fine, there's no standard way but...
Since the OP just needed to magnify the output range and re-centre it on 0, (-1 to 1 not 0 to 1) why not just double it and subtract 1?
I used this:
(x<0)*2-1
Or, forcing a bit shift:
(x<0)<<1-1
But the compiler will likely optimize that anyway.
add a comment |
I ran into this just today. So fine, there's no standard way but...
Since the OP just needed to magnify the output range and re-centre it on 0, (-1 to 1 not 0 to 1) why not just double it and subtract 1?
I used this:
(x<0)*2-1
Or, forcing a bit shift:
(x<0)<<1-1
But the compiler will likely optimize that anyway.
add a comment |
I ran into this just today. So fine, there's no standard way but...
Since the OP just needed to magnify the output range and re-centre it on 0, (-1 to 1 not 0 to 1) why not just double it and subtract 1?
I used this:
(x<0)*2-1
Or, forcing a bit shift:
(x<0)<<1-1
But the compiler will likely optimize that anyway.
I ran into this just today. So fine, there's no standard way but...
Since the OP just needed to magnify the output range and re-centre it on 0, (-1 to 1 not 0 to 1) why not just double it and subtract 1?
I used this:
(x<0)*2-1
Or, forcing a bit shift:
(x<0)<<1-1
But the compiler will likely optimize that anyway.
answered Aug 30 '15 at 16:27
AlidorAlidor
1
1
add a comment |
add a comment |
What about:
int sgn = x/fabs(x);
it should work out pretty good.
5
What happens when x == 0.0 ?
– Paul R
Jun 20 '17 at 7:30
1
and the performance would be pretty bad, too
– phuclv
Jun 30 '18 at 3:26
add a comment |
What about:
int sgn = x/fabs(x);
it should work out pretty good.
5
What happens when x == 0.0 ?
– Paul R
Jun 20 '17 at 7:30
1
and the performance would be pretty bad, too
– phuclv
Jun 30 '18 at 3:26
add a comment |
What about:
int sgn = x/fabs(x);
it should work out pretty good.
What about:
int sgn = x/fabs(x);
it should work out pretty good.
edited May 22 '17 at 13:56
gsamaras
51.2k24100186
51.2k24100186
answered May 22 '17 at 13:46
DanielDaniel
1
1
5
What happens when x == 0.0 ?
– Paul R
Jun 20 '17 at 7:30
1
and the performance would be pretty bad, too
– phuclv
Jun 30 '18 at 3:26
add a comment |
5
What happens when x == 0.0 ?
– Paul R
Jun 20 '17 at 7:30
1
and the performance would be pretty bad, too
– phuclv
Jun 30 '18 at 3:26
5
5
What happens when x == 0.0 ?
– Paul R
Jun 20 '17 at 7:30
What happens when x == 0.0 ?
– Paul R
Jun 20 '17 at 7:30
1
1
and the performance would be pretty bad, too
– phuclv
Jun 30 '18 at 3:26
and the performance would be pretty bad, too
– phuclv
Jun 30 '18 at 3:26
add a comment |
use:
`#define sgn(x) (x<0)`
for example:
`if(sng(n)) { etc ....}`
Or you may want to use some elaborated code, but casting first:
inline bool sgn_long(long x)
{
return ((x<0)? true: false);
}
1
The question was about a function that returns -1/0/+1 for negative/zero/positive numbers.
– Martin R
Nov 17 '17 at 10:03
add a comment |
use:
`#define sgn(x) (x<0)`
for example:
`if(sng(n)) { etc ....}`
Or you may want to use some elaborated code, but casting first:
inline bool sgn_long(long x)
{
return ((x<0)? true: false);
}
1
The question was about a function that returns -1/0/+1 for negative/zero/positive numbers.
– Martin R
Nov 17 '17 at 10:03
add a comment |
use:
`#define sgn(x) (x<0)`
for example:
`if(sng(n)) { etc ....}`
Or you may want to use some elaborated code, but casting first:
inline bool sgn_long(long x)
{
return ((x<0)? true: false);
}
use:
`#define sgn(x) (x<0)`
for example:
`if(sng(n)) { etc ....}`
Or you may want to use some elaborated code, but casting first:
inline bool sgn_long(long x)
{
return ((x<0)? true: false);
}
answered Nov 15 '17 at 22:25
Roberto TUNINETTIRoberto TUNINETTI
1
1
1
The question was about a function that returns -1/0/+1 for negative/zero/positive numbers.
– Martin R
Nov 17 '17 at 10:03
add a comment |
1
The question was about a function that returns -1/0/+1 for negative/zero/positive numbers.
– Martin R
Nov 17 '17 at 10:03
1
1
The question was about a function that returns -1/0/+1 for negative/zero/positive numbers.
– Martin R
Nov 17 '17 at 10:03
The question was about a function that returns -1/0/+1 for negative/zero/positive numbers.
– Martin R
Nov 17 '17 at 10:03
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f1903954%2fis-there-a-standard-sign-function-signum-sgn-in-c-c%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
9
What should it return for 0?
– Craig McQueen
Dec 14 '09 at 23:26
51
@Craig McQueen; that depends on if it is a positive zero or negative zero.
– ysth
Dec 15 '09 at 5:53
1
I noticed that you specified the return value as an integer. Are you looking for a solution that takes integers or floating point numbers?
– Mark Byers
Dec 15 '09 at 9:56
4
@ysth @Craig McQueen, false for floats too, no? sgn(x)'s definition says to return 0 if
x==0
. According to IEEE 754, negative zero and positive zero should compare as equal.– RJFalconer
Jun 4 '14 at 11:28
4
@ysth "it depends on positive zero or negative zero". In fact, it does not.
– RJFalconer
Jun 6 '14 at 8:10