105

数値の符号 ( signum 関数)を見つけるための重要な方法があるかどうか疑問に思いますか?
明白なソリューションよりも短い/高速/よりエレガントなソリューションである可能性があります

var sign = number > 0 ? 1 : number < 0 ? -1 : 0;

簡潔な答え!

これを使用すると、安全かつ高速になります (ソース: moz )

if (!Math.sign) Math.sign = function(x) { return ((x > 0) - (x < 0)) || +x; };

パフォーマンスと型強制比較フィドルを見たいと思うかもしれません

長い時間が経ちました。さらに、主に歴史的な理由によるものです。


結果

今のところ、これらのソリューションがあります。


1.明白で速い

function sign(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; }

1.1。kbecからの変更- 1 つのタイプのキャストが少なく、パフォーマンスが高く、短い[最速]

function sign(x) { return x ? x < 0 ? -1 : 1 : 0; }

注意: sign("0") -> 1


2.エレガント、短い、それほど速くない[最も遅い]

function sign(x) { return x && x / Math.abs(x); }

注意: sign(+-Infinity) -> NaNsign("0") -> NaN

ofInfinityは JS の正当な数値であるため、この解決策は完全には正しくないようです。


3.アート...しかし非常に遅い[最も遅い]

function sign(x) { return (x > 0) - (x < 0); }

4.ビットシフト
高速を使用しますが、sign(-Infinity) -> 0

function sign(x) { return (x >> 31) + (x > 0 ? 1 : 0); }

5.タイプセーフ[megafast]

! ブラウザー (特に chrome の v8) はいくつかの魔法の最適化を行っているようで、このソリューションは (1.1) よりもはるかにパフォーマンスが高いことが判明しました。

function sign(x) {
    return typeof x === 'number' ? x ? x < 0 ? -1 : 1 : x === x ? 0 : NaN : NaN;
}

ツール

改善大歓迎です!


[オフトピック] 受け入れられた回答

  • アンドレイ・タランツフ- アートの場合は +100 ですが、悲しいことに、明白なアプローチよりも約 5 倍遅くなります。

  • フレデリック・ハミディ- どういうわけか最も支持された答え(執筆中)であり、それはちょっとクールですが、それは間違いなく物事がどのように行われるべきかではありません. また、数字でもある無限数を正しく処理しません。

  • kbec - 明白な解決策の改善です。それほど革新的ではありませんが、すべてを総合すると、このアプローチが最善であると考えています。彼に投票してください:)

4

16 に答える 16

80

高速ソリューションのよりエレガントなバージョン:

var sign = number?number<0?-1:1:0
于 2012-01-31T12:32:30.673 に答える
29

数値をその絶対値で割ると、その符号も得られます。短絡論理 AND 演算子を使用すると、特殊なケースが可能に0なるため、最終的にそれで除算することはありません。

var sign = number && number / Math.abs(number);
于 2011-10-02T06:26:17.627 に答える
25

あなたが探している関数はsignumと呼ばれ、それを実装する最良の方法は次のとおりです。

function sgn(x) {
  return (x > 0) - (x < 0);
}
于 2013-01-19T20:05:40.307 に答える
14

これは、JavaScript (ECMAScript) の符号付きゼロをサポートすべきではありませんか? 「megafast」関数で 0 ではなく x を返すとうまくいくようです:

function sign(x) {
    return typeof x === 'number' ? x ? x < 0 ? -1 : 1 : x === x ? x : NaN : NaN;
}

これにより、ECMAScript の Math.sign ( MDN ) のドラフトと互換​​性があります。

x が正、負、ゼロのいずれであるかを示す、x の符号を返します。

  • x が NaN の場合、結果は NaN になります。
  • x が -0 の場合、結果は -0 です。
  • x が +0 の場合、結果は +0 です。
  • x が負で -0 でない場合、結果は -1 です。
  • x が正で +0 でない場合、結果は +1 になります。
于 2014-01-22T21:46:01.587 に答える
12

最新のブラウザがどうなっているのか気になる人のために、ES6版にはネイティブのMath.signメソッドがあります。サポートはこちらで確認できます。

基本的に、、、-1または10返しますNaN

Math.sign(3);     //  1
Math.sign(-3);    // -1
Math.sign('-3');  // -1
Math.sign(0);     //  0
Math.sign(-0);    // -0
Math.sign(NaN);   // NaN
Math.sign('foo'); // NaN
Math.sign();      // NaN
于 2015-04-20T05:38:24.403 に答える
1

楽しみのためにこれを追加すると思いました:

function sgn(x){
  return 2*(x>0)-1;
}

0 と NaN は -1 を返し
ます +/-Infinity で正常に動作します

于 2014-08-24T10:42:02.980 に答える
1

0-0だけでInfinityなく、すべての数値で機能するソリューション-Infinityは次のとおりです。

function sign( number ) {
    return 1 / number > 0 ? 1 : -1;
}

詳細については、「 +0 と -0 は同じですか? 」という質問を参照してください。


警告:現在の標準を含め、これらの回答はいずれもMath.sign、ケース0vsでは機能しません-0。これは問題にならないかもしれませんが、特定の物理実装では問題になる場合があります。

于 2016-01-04T23:18:34.340 に答える
0

Martijnの答えに非常に似ているのは

function sgn(x) {
    isNaN(x) ? NaN : (x === 0 ? x : (x < 0 ? -1 : 1));
}

より読みやすいと思います。また (または、見方によっては)、数値として解釈できるものも理解します。-1たとえば、 が表示されると返されます'-5'

于 2014-05-15T14:00:54.363 に答える
0

数値をビットシフトして、最上位ビット (MSB) を確認できます。MSB が 1 の場合、数値は負です。0 の場合、数値は正 (または 0) です。

于 2011-10-02T06:40:05.250 に答える
0

-0 と 0 を返す実用的な意味が見当たらないMath.signので、私のバージョンは次のとおりです。

function sign(x) {
    x = Number(x);
    if (isNaN(x)) {
        return NaN;
    }
    if (x === -Infinity || 1 / x < 0) {
        return -1;
    }
    return 1;
};

sign(100);   //  1
sign(-100);  // -1
sign(0);     //  1
sign(-0);    // -1
于 2016-11-30T12:05:37.563 に答える
0

コンパクトバージョンは次のとおりです。

let sign=x=>2*(x>=0)-1
//Tests
console.log(sign(0)); //1
console.log(sign(6)); //1
console.log(sign(Infinity)); //1
console.log(sign(-6)); //-1
console.log(sign(-Infinity)); //-1
console.log(sign("foo")); //-1

NaNおよびその他のエッジケースに対処したい場合は、これを使用します(ただし、長くなります):

let sign=x=>isNaN(x)?NaN:2*(x>=0)-1
//Tests
console.log(sign(0)); //1
console.log(sign(6)); //1
console.log(sign(Infinity)); //1
console.log(sign(-6)); //-1
console.log(sign(-Infinity)); //-1
console.log(sign("foo")); //NaN

sign(0)0 も返したい場合:

let sign=x=>isNaN(x)?NaN:(x?2*(x>=0)-1:0)
//Tests
console.log(sign(0)); //0
console.log(sign(6)); //1
console.log(sign(Infinity)); //1
console.log(sign(-6)); //-1
console.log(sign(-Infinity)); //-1
console.log(sign("foo")); //NaN
于 2021-03-30T07:08:33.307 に答える