99

I want to check if a number is negative. I’m searching for the easiest way, so a predefined JavaScript function would be the best, but I didn’t find anything yet. Here is what I have so far, but I don’t think that this is a good way:

function negative(number) {
  if (number.match(/^-\d+$/)) {
    return true;
  } else {
    return false;
  }
}
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Adam Halasz
  • 57,421
  • 66
  • 149
  • 213

7 Answers7

373

Instead of writing a function to do this check, you should just be able to use this expression:

(number < 0)

Javascript will evaluate this expression by first trying to convert the left hand side to a number value before checking if it's less than zero, which seems to be what you wanted.


Specifications and details

The behavior for x < y is specified in §11.8.1 The Less-than Operator (<), which uses §11.8.5 The Abstract Relational Comparison Algorithm.

The situation is a lot different if both x and y are strings, but since the right hand side is already a number in (number < 0), the comparison will attempt to convert the left hand side to a number to be compared numerically. If the left hand side can not be converted to a number, the result is false.

Do note that this may give different results when compared to your regex-based approach, but depending on what is it that you're trying to do, it may end up doing the right thing anyway.

  • "-0" < 0 is false, which is consistent with the fact that -0 < 0 is also false (see: signed zero).
  • "-Infinity" < 0 is true (infinity is acknowledged)
  • "-1e0" < 0 is true (scientific notation literals are accepted)
  • "-0x1" < 0 is true (hexadecimal literals are accepted)
  • " -1 " < 0 is true (some forms of whitespaces are allowed)

For each of the above example, the regex method would evaluate to the contrary (true instead of false and vice versa).

References

See also


Appendix 1: Conditional operator ?:

It should also be said that statements of this form:

if (someCondition) {
   return valueForTrue;
} else {
   return valueForFalse;
}

can be refactored to use the ternary/conditional ?: operator (§11.12) to simply:

return (someCondition) ? valueForTrue : valueForFalse;

Idiomatic usage of ?: can make the code more concise and readable.

Related questions


Appendix 2: Type conversion functions

Javascript has functions that you can call to perform various type conversions.

Something like the following:

if (someVariable) {
   return true;
} else {
   return false;
}

Can be refactored using the ?: operator to:

return (someVariable ? true : false);

But you can also further simplify this to:

return Boolean(someVariable);

This calls Boolean as a function (§15.16.1) to perform the desired type conversion. You can similarly call Number as a function (§15.17.1) to perform a conversion to number.

Related questions

Community
  • 1
  • 1
polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
  • 1
    @poly, in [ECMAScript 5](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf), it comes down to 11.8.5 (Abstract Relational Comparison). Unless *both* sides are strings, the abstract operation `ToNumber` is run on both sides during step 3. – Matthew Flaschen Aug 26 '10 at 03:02
  • 1
    @poly, I should have flipped back to 11.8.1 (The Less-than Operator) before. Step 6 explicitly coerces undefined to false. This also applies to the other relational operators. Probably, they decided it would be simpler to always evaluate to true or false, even though undefined is falsy. – Matthew Flaschen Aug 26 '10 at 04:36
  • 1
    No need for the parentheses in `return (condition);`, they're doing nothing. Also, that's not equivalent to the code that you say it is, since it will return the `condition` object itself rather than a Boolean. Perhaps you meant `return !!condition`? – Tim Down Aug 26 '10 at 08:42
  • 2
    Yes, that will work. I'd still prefer `!!` because using `Boolean` involves an extra function call and is therefore slower, and is also more characters. – Tim Down Aug 26 '10 at 10:59
  • @Tim, @Matthew: OK so on next revision I plan to have Appendix 3, Type conversion using operators, with the double complement instead of `Boolean` and unary plus instead of `Number`. Anything else I should add? I guess perhaps `~~` would also work instead of `+`, but that's all I can think of. – polygenelubricants Aug 26 '10 at 18:03
  • @Tim - !! is much less expressive though, and the parens are situationally clarifying at least. I'd argue that both the boolean cast and !! short-cut are unnecessary though and the function should just return the expression. JS duck types after all, you shouldn't be trying to concern yourself about type at emission, just at consumption. – annakata Aug 27 '10 at 07:49
  • annakata: My reference to parens was when the answer literally contained `return (condition);`. I think whether you find `!!foo` or `Boolean(foo)` more expressive is a matter of taste: it takes little time to get used to `!!` and it only takes a little thought to understand the first time you see it. Finally, I don't agree that returning the value of the expression is better: it could prevent a potentially large object from being garbage collected. – Tim Down Aug 27 '10 at 08:19
  • not always , Firefox pass the < 0 and make it negative , i was doing some animation few days ago and notice that Firefox throw an "parsing Error" when doing ... < 0 condition ,also happen in android 4.2 . so i use `number < 1` instead and add 1 in the length to make up the shortfall . – The Doctor Feb 25 '18 at 13:31
14
function negative(n) {
  return n < 0;
}

Your regex should work fine for string numbers, but this is probably faster. (edited from comment in similar answer above, conversion with +n is not needed.)

bcherry
  • 7,150
  • 2
  • 28
  • 37
13

This is an old question but it has a lot of views so I think that is important to update it.

ECMAScript 6 brought the function Math.sign(), which returns the sign of a number (1 if it's positive, -1 if it's negative) or NaN if it is not a number. Reference

You could use it as:

var number = 1;

if(Math.sign(number) === 1){
    alert("I'm positive");
}else if(Math.sign(number) === -1){
    alert("I'm negative");
}else{
    alert("I'm not a number");
}
Iván Rodríguez Torres
  • 4,293
  • 3
  • 31
  • 47
  • Nice but currently browsers and mobile support is limited according to: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign – Patrick Refondini Mar 11 '16 at 14:40
3

How about something as simple as:

function negative(number){
    return number < 0;
}

The * 1 part is to convert strings to numbers.

Wolph
  • 78,177
  • 11
  • 137
  • 148
  • 2
    The `* 1` is not necessary, as the comparison will do an implicit string->number conversion if needed. – Matthew Flaschen Aug 26 '10 at 02:54
  • @Matthew Flaschen: I wasn't sure if the behaviour would be consistent in all browsers so I added it. Can you confirm that this is consistent in all browsers cause I remember having some problems with this in the past. – Wolph Aug 26 '10 at 03:05
  • If you're concerned about making sure it's converted to a number, won't `+number` do the same thing? – Gabe Aug 26 '10 at 03:08
  • @Gabe: no it won't. Try doing `'foo' + 1` and you'll end up with `'foo1'`. So if you want to force a conversion to a number than it is usually the easiest to just do a `*1` instead. – Wolph Aug 26 '10 at 03:09
  • 2
    `+number` will be more efficient that `number * 1`, but in this case the `<` will cause `ToPrimitive` to be called on `number` all by itself, with hint `Number`. This behavior is in the spec, and consistent in all implementations. – bcherry Aug 26 '10 at 03:11
  • @WoLpH, `+number` is the unary `+` operator, not the binary `+`. They share the same token in code, but are distinct operators in the grammar. (To be more clear, the binary `+` is also overloaded even more, for both mathematical addition and string concatenation. The unary `+` is not overloaded, it is purely mathematical.) – bcherry Aug 26 '10 at 03:13
  • @WoLpH, he didn't say `'foo' + 1`, he said `+number`, which for your example is `+'foo'`. That gives `NaN`, as expected. You can also do `parseInt` or `parseFloat` (depending on whether you want an integer result). However, as far as the current standard is concerned (possible browser bugs aside), none is required here. – Matthew Flaschen Aug 26 '10 at 03:16
  • @bcherry: ah, I didn't realize the unary `+` would be called instead. I'm not that well versed in Ecmascript I suppose ;) Thanks for the information. @Matthew Flaschen: Indeed, I misunderstood what he meant. Still not sure about that browser bug though... I remember seeing it with some old IE versions. But that's probably not relevant anymore so I'll remove it. – Wolph Aug 26 '10 at 03:31
2

If you really want to dive into it and even need to distinguish between -0 and 0, here's a way to do it.

function negative(number) {
  return !Object.is(Math.abs(number), +number);
}

console.log(negative(-1));  // true
console.log(negative(1));   // false
console.log(negative(0));   // false
console.log(negative(-0));  // true
Hao Wu
  • 17,573
  • 6
  • 28
  • 60
1

In ES6 you can use Math.sign function to determine if,

1. its +ve no
2. its -ve no
3. its zero (0)
4. its NaN


console.log(Math.sign(1))        // prints 1 
console.log(Math.sign(-1))       // prints -1
console.log(Math.sign(0))        // prints 0
console.log(Math.sign("abcd"))   // prints NaN
JTeam
  • 1,455
  • 1
  • 11
  • 16
1

An nice way that also checks for positive and negative also...

function ispositive(n){
    return 1/(n*0)===1/0
}

console.log( ispositive(10) )  //true
console.log( ispositive(-10) )  //false
console.log( ispositive(0) )  //true
console.log( ispositive(-0) )  //false

essentially compares Infinity with -Infinity because 0===-0// true

treeseal7
  • 739
  • 8
  • 22