জাভাস্ক্রিপ্টে সংখ্যা.সাইন ()


101

আশ্চর্য কি যদি সংখ্যার সাইন ( সাইনাম ফাংশন ) সন্ধানের কোনও অনর্থক উপায় থাকে ?
সুস্পষ্ট সমাধানের চেয়ে কম / দ্রুত / আরও মার্জিত সমাধান হতে পারে

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

সংক্ষিপ্ত উত্তর!

এটি ব্যবহার করুন এবং আপনি নিরাপদ এবং দ্রুত থাকবেন (উত্স: মোজ )

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

আপনার কর্মক্ষমতা এবং ধরন-উপর চাপ তুলনা তাকান করতে পারেন বেহালার

দীর্ঘ সময় কেটে গেছে। আরও প্রধানত historicalতিহাসিক কারণে।


ফলাফল

আপাতত আমাদের এই সমাধানগুলি রয়েছে:


1. স্পষ্টত এবং দ্রুত

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

1.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) -> NaN ,sign("0") -> NaN

জেএসে Infinityএকটি আইনী সংখ্যা হিসাবে এই সমাধানটি পুরোপুরি সঠিক বলে মনে হচ্ছে না।


৩. শিল্প ... তবে খুব ধীর [ধীর]

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

৪. বিট-শিফট দ্রুত ব্যবহার করা হচ্ছে
, তবেsign(-Infinity) -> 0

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

৫. টাইপ-সেফ [মেগাফাস্ট]

! ব্রাউজারগুলির মতো মনে হয় (বিশেষত ক্রোমের ভি 8) কিছু যাদু অপ্টিমাইজেশান তৈরি করে এবং এই সমাধানটি 2 টি অতিরিক্ত ক্রিয়াকলাপ থাকা সত্ত্বেও (1.1) এর চেয়ে অন্যদের তুলনায় অনেক বেশি পারফরম্যান্ট হিসাবে প্রমাণিত হয় এবং যৌক্তিকভাবে কখনই দ্রুত হতে পারে না।

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

সরঞ্জামসমূহ

  • jsperf preformance টেস্ট;
  • ভাজা - টাইপ-কাস্ট পরীক্ষা;

উন্নতি স্বাগত!


[অফটোপিক] গৃহীত উত্তর

  • আন্ড্রে তারানসভ - শিল্পের জন্য +100, তবে দুঃখের বিষয় এটি সুস্পষ্ট পদ্ধতির চেয়ে প্রায় 5 গুণ ধীর

  • ফ্রিডরিক হামিদি - একরকম সর্বাধিক উত্সাহিত উত্তর (সময়ের লেখার জন্য) এবং এটি দারুণ সুন্দর, তবে জিনিসগুলি কীভাবে করা উচিত তা অবশ্যই নয় im এছাড়াও এটি ইনফিনিটি সংখ্যাগুলি সঠিকভাবে পরিচালনা করে না, এটিও সংখ্যা you

  • kbec - সুস্পষ্ট সমাধানের একটি উন্নতি। বিপ্লবী নয়, সকলকে একত্রিত করে আমি এই পদ্ধতিকে সর্বোত্তম বিবেচনা করি। তাকে ভোট দিন :)



1
প্রতিটি অ্যালগোরিদম পরীক্ষা করার জন্য আমি জেএসপিআইপি পরীক্ষা (বিভিন্ন ধরণের ইনপুট সহ) তৈরি করেছি, যা এখানে পাওয়া যাবে: jsperf.com/signs ফলাফল এই পোস্টে তালিকাভুক্ত নাও হতে পারে!
আলবা মেন্ডেজ

2
@ অবনমিত, তাদের মধ্যে কোনটি? অবশ্যই, আপনি যদি test everythingসংস্করণটি চালান , সেফ বিশেষ মানগুলি পরীক্ষা করতে অস্বীকার করবে, তাই এটি আরও দ্রুত হবে! only integersপরিবর্তে পরীক্ষা চালানোর চেষ্টা করুন । এছাড়াও, জেএসপিফার কেবল তার কাজ করছে, এটি পছন্দ করার বিষয় নয়। :)
আলবা মেন্ডিজ

2
জেএসপিফার টেস্ট অনুসারে এটি দেখা যাচ্ছে যে typeof x === "number"পারফরমেন্সে কিছু জাদু রাখে। দয়া করে আরও রান করুন, বিশেষত এফএফ, অপেরা এবং আইই এটি পরিষ্কার করার জন্য।
disfated

4
সম্পূর্ণতার জন্য আমি এফএফ 25 এ উপস্থিত হয়ে ক্রোমে আসার জন্য Math.sign()(0 === 0, "নিরাপদ" এর চেয়ে দ্রুত নয়) এর জন্য একটি নতুন পরীক্ষা jsperf.com/signs/7 যুক্ত করেছি ।
অ্যালেক্স কে।

উত্তর:



28

সংখ্যাটিকে তার নিখুঁত মান দ্বারা ভাগ করাও তার চিহ্ন দেয়। সংক্ষিপ্ত-সার্কিট লজিকাল এবং অপারেটর ব্যবহার করে আমাদের বিশেষ ক্ষেত্রে মঞ্জুরি দেয় 0যাতে আমরা এর দ্বারা ভাগ করে না ফেলে:

var sign = number && number / Math.abs(number);

6
আপনি সম্ভবত এই var sign = number && number / Math.abs(number);ক্ষেত্রে number = 0
চাইবেন

@ নুল ইউজার এক্সসেপশন, আপনি একদম ঠিক আছেন, 0বিশেষ-ক্ষেত্রেযুক্ত হওয়া দরকার। উত্তর অনুসারে আপডেট করা হয়েছে। ধন্যবাদ :)
ফ্রেডরিক হামিদি

আপনি আপাতত সেরা। তবে আমি আশা করি ভবিষ্যতে আরও উত্তর থাকবে।
বিচ্ছুরিত

24

আপনি যে ফাংশনটির সন্ধান করছেন তাকে সাইনাম বলা হয় এবং এটি কার্যকর করার সর্বোত্তম উপায় হ'ল:

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

3
অপেক্ষা করুন। ভুল রয়েছে: (x = -2; x <= 2; x ++) কনসোল.লগের জন্য ((x> 1) - (x <1)); [-1, -1, -1, 0, 1] এর জন্য (x = -2; x <= 2; x ++) কনসোল.লগ ((x> 0) - (x <0)); সঠিক [-1, -1, 0, 1, 1] দেয়
20:43

13

এটি কি জাভাস্ক্রিপ্টের (ECMAScript এর) স্বাক্ষরিত শূন্যগুলিকে সমর্থন করবে না? "মেগাফাস্ট" ফাংশনে 0 এর পরিবর্তে x ফেরার সময় এটি কাজ করছে বলে মনে হচ্ছে:

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

এটি এটি ECMAScript এর ম্যাথ.সাইন ( MDN ) এর খসড়ার সাথে সামঞ্জস্যপূর্ণ করে তোলে :

X ধনাত্মক, negativeণাত্মক বা শূন্য কিনা তা নির্দেশ করে x এর চিহ্নটি প্রদান করে।

  • X যদি NaN হয় তবে ফলাফলটি NaN হয়।
  • X যদি −0 হয় তবে ফলাফলটি −0 হয়।
  • X +0 হলে ফলাফলটি 0 হয়।
  • X যদি negativeণাত্মক হয় এবং −0 না হয় তবে ফলাফলটি −1 হয়।
  • X যদি ইতিবাচক হয় এবং +0 না হয় তবে ফলাফলটি +1 হয়।

অবিশ্বাস্যভাবে দ্রুত এবং আকর্ষণীয় প্রক্রিয়া, আমি মুগ্ধ। আরও পরীক্ষার জন্য অপেক্ষা।
কেবিইচ

10

যে সমস্ত লোকেরা সর্বশেষ ব্রাউজারগুলির সাথে কী চলছে তা আগ্রহী, ES6 সংস্করণে একটি নেটিভ ম্যাথ.সাইন পদ্ধতি রয়েছে। আপনি সমর্থন এখানে পরীক্ষা করতে পারেন ।

মূলত এটি ফেরৎ -1, 1, 0বা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

4
var sign = number >> 31 | -number >>> 31;

যদি আপনার অনন্তের প্রয়োজন না হয় এবং জেনে রাখুন যে সংখ্যাটি একটি পূর্ণসংখ্যা, ওপেনডেডকে -7 উত্সে পাওয়া যায়: java.lang.Integer.signum()


1
এটি -0.5 এর মতো ছোট নেতিবাচক ভগ্নাংশের জন্য ব্যর্থ। (দেখে মনে হচ্ছে উত্সটি নির্দিষ্টভাবে পূর্ণসংখ্যার জন্য বাস্তবায়ন থেকে এসেছে)
59-

1

আমি ভেবেছিলাম আমি এটি কেবল মজাদার জন্য যুক্ত করব:

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

0 এবং NaN
+/- অনন্ত উপর জরিমানা -1 কাজ করবে


1

একটি সমাধান যে সব সংখ্যার উপর কাজ করে, সেইসাথে 0এবং -0, সেইসাথে Infinityএবং-Infinity , হল:

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

প্রশ্নটি দেখুন " +0 এবং -0 এক?আরও তথ্যের জন্য " "


সতর্কতা: এখনকার মান সহ এই উত্তরগুলির কোনওটিই Math.signমামলা 0বনাম নিয়ে কাজ করবে না -0। এটি আপনার পক্ষে সমস্যা নাও হতে পারে তবে নির্দিষ্ট পদার্থবিজ্ঞানের বাস্তবায়নে এটি বিষয়টি বিবেচনা করতে পারে।


0

আপনি নম্বরটি কিছুটা স্থানান্তর করতে এবং সর্বাধিক গুরুত্বপূর্ণ বিট (এমএসবি) পরীক্ষা করতে পারেন। এমএসবি যদি 1 হয় তবে সংখ্যাটি নেতিবাচক। যদি এটি 0 হয় তবে সংখ্যাটি ইতিবাচক (বা 0)।


@ নুল ইউজার এক্সসেপশন আমি এখনও ভুল হতে পারি তবে আমার পড়া থেকে "সমস্ত বিটওয়াইজ অপারেটরগুলির অপারেন্ডস বিগ-এন্ডিয়ান অর্ডারে এবং দু'জনের পরিপূরক বিন্যাসে স্বাক্ষরিত 32-বিট পূর্ণ সংখ্যায় রূপান্তরিত হয়।" থেকে নেওয়া MDN
Brombomb

এটি এখনও একটি ভয়াবহ কাজের মতো মনে হয়; আপনাকে এখনও 1 এবং 0 তে -1 এবং 1 তে রূপান্তর করতে হবে এবং 0 এরও যত্ন নিতে হবে। ওপি যদি এটি চেয়েছিল, কেবল এটি ব্যবহার করা সহজ হবেvar sign = number < 0 : 1 : 0
নুল ইউজারএক্সেপশন

+1 টি। যদিও শিফট করার দরকার নেই, আপনি ঠিক n & 0x80000000একটি বিটমাস্কের মতো করতে পারেন । 0,1 তে রূপান্তর করার জন্য, -1:n && (n & 0x80000000 ? -1 : 1)
ডেভিন

@ ডেভিন কি সমস্ত বিটমাস্কের সাথে কাজ করার গ্যারান্টিযুক্ত? আমি প্লাগ ইন করি -5e32এবং এটি ভেঙে যায়।
নালুউজারএক্সসেপশন

@ নাল ইউজারএক্সেপশন ఠ_ఠ, মানগুলি প্রয়োগ করার সময় একই চিহ্ন রাখে এমন নম্বর ToInt32। আপনি যদি সেখানে (বিভাগ 9.5) পড়ে থাকেন তবে এমন একটি মডুলাস রয়েছে যা সংখ্যার মানকে প্রভাবিত করে যেহেতু 32-বিট পূর্ণসংখ্যার পরিসীমা js সংখ্যা প্রকারের পরিসরের চেয়ে কম হয়। সুতরাং এটি সেই মানগুলি বা অসম্পূর্ণতার জন্য কাজ করবে না। যদিও আমি উত্তরটি এখনও পছন্দ করি।
ডেভিন

0

আমি ঠিক একই প্রশ্ন করতে চলেছিলাম, তবে আমি লেখার কাজ শেষ করার আগেই একটি সমাধানে এসেছি, এই প্রশ্নটি ইতিমধ্যে বিদ্যমান আছে, তবে এই সমাধানটি দেখেনি saw

(n >> 31) + (n > 0)

যদিও এটি একটি ত্রিনিয়ার যুক্ত করে দ্রুত হয়েছে বলে মনে হচ্ছে (n >> 31) + (n>0?1:0)


খুব সুন্দর. আপনার কোডটি (1) এর চেয়ে কিছুটা দ্রুত গতিতে দেখায়। (n> 0? 1: 0) কোনও প্রকারের castালাইয়ের দ্রুত বিচেজ নয়। একমাত্র অসম্পূর্ণ মুহূর্তটি সাইন (-ইনফিনিটি) ০. আপডেটেড পরীক্ষা দেয়।
বিচ্ছিন্ন

0

মার্তিজানের উত্তরটির সাথে খুব মিল

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

আমি এটি আরও পাঠযোগ্য বলে মনে করি। এছাড়াও (বা, আপনার দৃষ্টিভঙ্গির উপর নির্ভর করে, তবে) এটি এমন জিনিসগুলিও ছাঁটাই করে যা একটি সংখ্যা হিসাবে ব্যাখ্যা করা যায়; উদাহরণস্বরূপ, -1উপস্থাপিত হলে এটি ফিরে আসে '-5'


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

এই সংকেত ফাংশন নয়
disfated

0

আমার জানা পদ্ধতিগুলি নিম্নরূপ:

Math.sign (ঢ)

var s = Math.sign(n)

এটি নেটিভ ফাংশন, তবে কোনও ফাংশন কলের ওভারহেডের কারণে এটি সবচেয়ে ধীরে slow তবে এটি 'NaN' পরিচালনা করে যেখানে নীচের অন্যান্যরা কেবল 0 (যেমন ম্যাথ.সাইন ('abc') NaN) ধরে নিতে পারে।

((এন> 0) - (এন <0)

var s = ((n>0) - (n<0));

সেক্ষেত্রে কেবল বাম বা ডানদিকে সাইন উপর ভিত্তি করে 1 হতে পারে। এর ফলাফল 1-0(1), 0-1(-1), বা 0-0(0) এ আসে।

নীচের পরের ক্রোমের সাথে এইটির গতি মনে হচ্ছে ঘাড় এবং ঘাড়।

(ঢ >> 31) | (!! ঢ)

var s = (n>>31)|(!!n);

"সাইন-প্রচার ডান শিফট" ব্যবহার করে। মূলত ৩১ টি ড্রপ করে চিহ্ন বাদে সমস্ত বিট ফেলে দেয়। যদি চিহ্নটি সেট করা থাকে, এটি -1 এ ফলাফল হয়, অন্যথায় এটি 0 হয় এর ডানদিকে |ধনাত্মক পরীক্ষা করে মানটি বুলিয়ান রূপান্তর করে (0 বা 1 [বিটিডাব্লু: অ-সংখ্যাযুক্ত স্ট্রিং, যেমন)!!'abc' , 0 ক্ষেত্রে 0 হয়ে এবং না না]] এরপরে বিটগুলি একত্রিত করতে কিছুটা দিকের বা অপারেশন ব্যবহার করে।

এটি ব্রাউজারগুলির জুড়ে সেরা গড় পারফরম্যান্স বলে মনে হচ্ছে (কমপক্ষে ক্রোম এবং ফায়ারফক্সে সেরা) তবে সেগুলির মধ্যে সবথেকে দ্রুত নয়। কোনও কারণে, টর্নারি অপারেটর আইই তে দ্রুত হয়।

এন এন <0 -1: 1: 0

var s = n?n<0?-1:1:0;

কোনও কারণে IE এ দ্রুততম।

jsPerf

পরীক্ষাগুলি সম্পাদিত: https://jsperf.com/get-sign-from-value


0

আমার দুটি সেন্ট, এমন একটি ফাংশন সহ যা ম্যাথ.সাইন এর মতো একই ফলাফল দেয়, যেমন সাইন (-0) -> -0, সাইন (-ইনফিনিটি) -> -অনফিনিটি, সাইন (নাল) -> 0 , সাইন (অপরিজ্ঞাত) -> NaN, ইত্যাদি

function sign(x) {
    return +(x > -x) || (x && -1) || +x;
}

জাসস্পিফ আমাকে একটি পরীক্ষা বা সংশোধন তৈরি করতে দেয় না, আপনাকে পরীক্ষা দেওয়ার ব্যবস্থা না করতে পেরে দুঃখিত (আমি jsbench.github.io একটি চেষ্টা করেছি, তবে ফলাফল জেএসপিফের সাথে তুলনায় একে অপরের আরও কাছাকাছি বলে মনে হচ্ছে ...)

কেউ যদি দয়া করে এটি কোনও জাস্পিফ পুনর্বিবেচনার সাথে যুক্ত করতে পারতেন তবে আমি এটি জানতে আগ্রহী যে এটি পূর্বের প্রদত্ত সমস্ত সমাধানগুলির সাথে কীভাবে তুলনা করে ...

ধন্যবাদ!

জিম।

সম্পাদনা :

আমার লেখা উচিত ছিল:

function sign(x) {
    return +(x > -x) || (+x && -1) || +x;
}

( (+x && -1)পরিবর্তে (x && -1)) sign('abc')সঠিকভাবে পরিচালনা করার জন্য (-> NaN)


0

ম্যাথ.সাইনটি আইই ১১ তে সমর্থিত নয় I

Math.sign = Math.sign || function(number){
    var sign = number ? ( (number <0) ? -1 : 1) : 0;
    return sign;
};

এখন, কেউ সরাসরি ম্যাথ.সাইন ব্যবহার করতে পারেন।


1
আপনি আমার প্রশ্ন আপডেট করার জন্য আমাকে ধাক্কা দিয়েছেন। এটি জিজ্ঞাসা করার পরে 8 বছর কেটে গেল। আমার jsfiddle এএস 6 এবং উইন্ডো. পারফরম্যান্স এপিআইতে আপডেট করেছে। তবে আমি মজিলার সংস্করণটিকে পলিফিল হিসাবে পছন্দ করি কারণ এটি ম্যাথ.সাইন এর ধরণের কর্কিংয়ের সাথে মেলে। পারফরম্যান্স আজকাল খুব একটা উদ্বেগের বিষয় নয়।
26:53
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.