সি / সি ++ এ কি কোনও স্ট্যান্ডার্ড সাইন ফাংশন (সিগনাম, এসএনজিএন) রয়েছে?


409

আমি এমন একটি ফাংশন চাই যা নেতিবাচক সংখ্যার জন্য -1 এবং ইতিবাচক সংখ্যার জন্য +1 প্রদান করে। http://en.wikedia.org/wiki/Sign_function এটি নিজের লেখা আমার পক্ষে যথেষ্ট সহজ, তবে এটি এমন কিছু বলে মনে হচ্ছে যা কোথাও কোনও স্ট্যান্ডার্ড লাইব্রেরিতে থাকা উচিত।

সম্পাদনা: বিশেষত, আমি ফ্লোটে কাজ করার জন্য একটি ফাংশন সন্ধান করছিলাম।


13
এটি 0 এর জন্য কী ফিরবে?
ক্রেগ ম্যাককুইন

61
@ ক্রেইগ ম্যাককুইন; এটি নির্ভর করে যদি এটি ইতিবাচক শূন্য বা নেতিবাচক শূন্য হয়।
ysth

1
আমি লক্ষ্য করেছি যে আপনি একটি পূর্ণসংখ্যা হিসাবে রিটার্ন মান নির্দিষ্ট করেছেন। আপনি কি এমন কোনও সমাধান খুঁজছেন যা পূর্ণসংখ্যা বা ভাসমান পয়েন্ট সংখ্যা নেয়?
মার্ক বাইয়ার্স

6
@ysth @ ক্রেইগ ম্যাককুইন, ভাসমানদের জন্যও মিথ্যা, না? sgn (x) এর সংজ্ঞা বলে যদি 0 ফিরে আসে x==0আইইইই 754 অনুসারে , নেতিবাচক শূন্য এবং ধনাত্মক শূন্য সমান হিসাবে তুলনা করা উচিত।
আরজেফালকোনার

5
@ysth "এটি ইতিবাচক শূন্য বা নেতিবাচক শূন্যের উপর নির্ভর করে"। আসলে, এটা না।
আরজেফালকোনার

উত্তর:


506

অবাক করা কেউ এখনও টাইপ-সেফ সি ++ সংস্করণ পোস্ট করেন নি:

template <typename T> int sgn(T val) {
    return (T(0) < val) - (val < T(0));
}

উপকারিতা:

  • আসলে সাইনাম প্রয়োগ করে (-1, 0, বা 1) এখানে কপিসাইন ব্যবহার করে প্রয়োগগুলি কেবল -1 বা 1 প্রদান করে, যা সাইনাম নয়। এছাড়াও, এখানে কিছু বাস্তবায়নগুলি কোনও int এর পরিবর্তে একটি ভাসা (বা টি) ফিরিয়ে দিচ্ছে যা অপব্যয় বলে মনে হচ্ছে।
  • ইনটিজার 0, এবং শোধনযোগ্য থেকে কাঠামোগত ইনটস, ফ্লোটস, ডাবলস, স্বাক্ষরবিহীন শর্টস বা কোনও কাস্টম ধরণের জন্য কাজ করে।
  • দ্রুত! copysignধীরে ধীরে, বিশেষ করে আপনার প্রচার করতে হবে এবং আবার সংকীর্ণ হওয়া প্রয়োজন। এটি শাখাবিহীন এবং সর্বোত্তমভাবে অনুকূলিত
  • স্ট্যান্ডার্ড-অনুবর্তী! বিটশিফ্ট হ্যাকটি ঝরঝরে, তবে কেবল কিছু বিট উপস্থাপনার জন্য কাজ করে এবং যখন আপনার স্বাক্ষরযুক্ত স্বাক্ষরিত টাইপ থাকে তখন কাজ করে না। উপযুক্ত হলে এটি ম্যানুয়াল বিশেষীকরণ হিসাবে সরবরাহ করা যেতে পারে।
  • সঠিক! শূন্যের সাথে সাধারণ তুলনাগুলি মেশিনের অভ্যন্তরীণ উচ্চ-নির্ভুলতার উপস্থাপনা (উদাহরণস্বরূপ x87 এর উপরে 80 বিট) বজায় রাখতে পারে এবং অকালকে গোল থেকে শূন্য এড়াতে পারে।

আদেশ সহকারে:

  • এটি একটি টেম্পলেট তাই কিছু পরিস্থিতিতে সংকলন হতে আরও বেশি সময় লাগতে পারে।
  • স্পষ্টতই কিছু লোক মনে করেন যে একটি নতুন, কিছুটা রহস্যময় এবং খুব ধীর মানক লাইব্রেরি ফাংশন যা এমনকি সাইনাম বাস্তবায়ন করে না এটি আরও বোধগম্য।
  • < 0চেক অংশ জিসিসি ট্রিগার -Wtype-limitsযখন একটি স্বাক্ষরবিহীন টাইপ জন্য instantiated সতর্কবার্তা। আপনি কিছু ওভারলোড ব্যবহার করে এড়াতে পারেন:

    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>());
    }
    

    (যা প্রথম ক্যাভিয়াতের একটি ভাল উদাহরণ))


18
@ জিএমান: জিসিসি এখনই (৪.৫) টেমপ্লেট ফাংশনগুলির জন্য ইনস্ট্যান্টেশনগুলির সংখ্যার তুলনায় চতুর্মুখী হওয়া বন্ধ করেছে এবং ম্যানুয়ালি লিখিত ফাংশন বা স্ট্যান্ডার্ড সি প্রিপ্রসেসরের তুলনায় এগুলি পার্স এবং ইনস্ট্যান্টেট করার জন্য মারাত্মকভাবে আরও ব্যয়বহুল। লিঙ্কারটিকে সদৃশ ইনস্ট্যান্টেশনগুলি সরানোর জন্য আরও কাজ করতে হবে। টেমপ্লেটগুলি # টি অন্তর্ভুক্ত-ইন-# অন্তর্ভুক্তকেও উত্সাহ দেয়, যা নির্ভরতা গণনাটিকে আরও বেশি ফাইল পুনরায় সংযোগ করতে বাধ্য করতে পরিবর্তনগুলি আরও দীর্ঘ এবং ছোট (প্রায়শই বাস্তবায়ন, ইন্টারফেস নয়) পরিবর্তনগুলি করে।

15
@ জো: হ্যাঁ, এবং এখনও কোনও লক্ষণীয় ব্যয় নেই। সি ++ টেমপ্লেট ব্যবহার করে, এটি আমাদের সকলকে বুঝতে, গ্রহণ করতে এবং শেষ করতে হবে।
GManNickG

42
অপেক্ষা করুন, এই "কপিসাইনটি স্লো" ব্যবসায় কী ...? বর্তমান কম্পাইলার ব্যবহার (ছ ++, 4.6+, ঝনঝন শব্দ ++, 3.0), std::copysignফলে মনে হয় চমৎকার আমার জন্য কোড: 4 নির্দেশাবলী (inlined), কোন শাখাবিন্যাস, সম্পূর্ণরূপে FPU ব্যবহার করে। বিপরীতে এই উত্তরে প্রদত্ত রেসিপিটি আরও খারাপ কোড উত্পন্ন করে (বহুগুণ সহ আরও অনেক নির্দেশাবলী, পূর্ণসংখ্যা ইউনিট এবং
এফপিইউয়ের

14
@ স্নোগলথোর্প: আপনি যদি কোনও ইনটকে কল দিচ্ছেন তবে copysignএটি ভাসমান / দ্বৈত হয়ে উঠতে উত্সাহ দেয় এবং ফিরতে আবার সংকীর্ণ করতে হবে। আপনার সংকলক সেই পদোন্নতিটি অপ্টিমাইজ করতে পারে তবে মান দ্বারা গ্যারান্টিযুক্ত এমন কোনও প্রস্তাব আমি পাই না। এছাড়াও কপিসিগনের মাধ্যমে সাইনাম বাস্তবায়নের জন্য আপনাকে 0 কে ম্যানুয়ালি হ্যান্ডেল করতে হবে - দয়া করে নিশ্চিত হন যে কোনও পারফরম্যান্সের তুলনায় আপনি এটি অন্তর্ভুক্ত করেছেন।

53
প্রথম সংস্করণটি শাখাবিহীন নয়। লোকেরা কেন মনে করে যে একটি অভিব্যক্তিতে ব্যবহৃত তুলনাটি একটি শাখা তৈরি করবে না? এটি বেশিরভাগ আর্কিটেকচারে হবে। কেবলমাত্র একটি প্রসেসর যাদের একটি সেমিওয়েভ (বা পূর্বাভাস) রয়েছে সেগুলি শাখাবিহীন কোড উত্পন্ন করবে, তবে তারা এটিটি টের্নারিগুলির জন্যও করবে বা যদি / অন্যথায় এটি জয় হয়।
প্যাট্রিক শ্লিয়েটার

271

আমি এটির জন্য কোনও স্ট্যান্ডার্ড ফাংশন জানি না। যদিও এটি লেখার একটি আকর্ষণীয় উপায় এখানে:

(x > 0) - (x < 0)

এটি করার আরও একটি পঠনযোগ্য উপায়:

if (x > 0) return 1;
if (x < 0) return -1;
return 0;

আপনি যদি টার্নারি অপারেটর পছন্দ করেন তবে আপনি এটি করতে পারেন:

(x > 0) ? 1 : ((x < 0) ? -1 : 0)

7
মার্ক রান্সম, আপনার অভিব্যক্তিগুলি এর জন্য ভুল ফলাফল দেয় x==0
অবাক

3
@ সোভান্তে: "প্রতিটি অপারেটর <, >... নির্দিষ্ট সম্পর্কটি সত্য হলে 1 এবং এটি মিথ্যা হলে 0 উপার্জন করবে"
স্টিফেন ক্যানন

11
@ সোভান্ট: হুবহু নয় এর মান 0"মিথ্যা"; অন্য কোনও মান "সত্য"; তবে, সম্পর্কিত এবং সাম্য অপারেটরগুলি সর্বদা ফিরে আসে 0বা 1(স্ট্যান্ডার্ড 6.5.8 এবং 6.5.9 দেখুন)। - প্রকাশের মান a * (x == 42)হয় হয় 0বা হয় a
পিএমজি

21
উচ্চ-পারফরম্যান্স মার্ক, আমি অবাক হয়েছি যে আপনি সি ++ ট্যাগটি মিস করেছেন। এই উত্তরটি খুব বৈধ এবং ডাউন-ভোটের যোগ্য নয়। তদুপরি, আমি এটি উপলব্ধ থাকলেও copysignঅবিচ্ছেদ্য জন্য ব্যবহার করব না x
অবাক

6
সত্যিকারের প্ল্যাটফর্মে কোনও কোড জিসিসি / জি ++ / অন্য কোনও সংকলকটি আসলে কি পরীক্ষা করেছে? আমার অনুমান "শাখাবিহীন" সংস্করণটির পরিবর্তে দুটি শাখা ব্যবহার করে। বিটশিফিং সম্ভবত অনেক দ্রুত - এবং পারফরম্যান্সের দিক থেকে আরও বহনযোগ্য।
জর্জেন ফোগ

192

কপিসাইন () নামে একটি সি 99 গণিতের লাইব্রেরি ফাংশন রয়েছে, যা একটি যুক্তির থেকে চিহ্ন এবং অন্যটির থেকে নিখুঁত মান নেয়:

result = copysign(1.0, value) // double
result = copysignf(1.0, value) // float
result = copysignl(1.0, value) // long double

মান চিহ্নের উপর নির্ভর করে আপনাকে +/- 1.0 এর ফলাফল দেবে। নোট করুন যে ভাসমান পয়েন্ট শূন্যগুলি স্বাক্ষরিত হয়েছে: (+0) +1 প্রদান করবে এবং (-0) ফলন করবে -1।


57
এটিকে উর্ধ্বমুখী করে সর্বাধিক জনপ্রিয় উত্তরকে অগ্রাহ্য করেছেন। বিস্ময়ে বাম রিলিং যে SO সম্প্রদায় মনে হয় একটি স্ট্যান্ডার্ড লাইব্রেরি ফাংশন ব্যবহার করতে একটি হ্যাক পছন্দ করে। প্রোগ্রামিংয়ের দেবতারা আপনারা সবাইকে ভাষার মানের সাথে অপরিচিত চতুর প্রোগ্রামারদের দ্বারা ব্যবহৃত হ্যাকগুলি বোঝার চেষ্টা করার জন্য নিন্দা জানাতে পারেন। হ্যাঁ, আমি জানি আমার তাই প্রতিনিধির একটি টন খরচ যাচ্ছে, কিন্তু আমি বরং তোমাদের মধ্যে বাকি তুলনায় comingstorm সঙ্গে পাশ চাই ...
হাই পারফরমেন্স মার্ক

34
এটি নিকটে, তবে এটি শূন্যের জন্য ভুল উত্তর দেয় (কমপক্ষে প্রশ্নের উইকিপিডিয়া নিবন্ধ অনুযায়ী)। ভাল পরামর্শ যদিও। যাইহোক +1।
মার্ক বাইয়ার্স

4
আপনি যদি একটি পূর্ণসংখ্যার চান, বা আপনি যদি শূন্যগুলির জন্য সঠিক সাইনাম ফলাফল চান, তবে আমি মার্ক বাইয়ার্সের উত্তরটি পছন্দ করি, যা খুব সুন্দরভাবে মার্জিত! আপনি যদি উপরের বিষয়ে চিন্তা না করে থাকেন তবে অ্যাপ্লিকেশনের উপর নির্ভর করে কপিসাইন () এর পারফরম্যান্স অ্যাডভান্স থাকতে পারে - যদি আমি একটি সমালোচনামূলক লুপটি অনুকূল করে তুলি তবে আমি উভয়ই চেষ্টা করে দেখতাম।
আসন্ন ঝড়

10
1) C99 সর্বত্র সম্পূর্ণরূপে সমর্থিত নয় (ভিসি ++ বিবেচনা করুন); 2) এটি একটি সি ++ প্রশ্ন। এটি একটি ভাল উত্তর, তবে আপোভোটেড উত্তরটিও কার্যকর হয় এবং এটি আরও ব্যাপকভাবে প্রযোজ্য।
পাভেল মিনায়েভ

5
ত্রাতা! -0.0 এবং 0.0 এর মধ্যে নির্ধারণের জন্য একটি উপায় প্রয়োজন
ইলফুর ওয়েজ

79

দেখে মনে হচ্ছে বেশিরভাগ উত্তরই মূল প্রশ্নটি মিস করেছে।

সি / সি ++ এ কি কোনও স্ট্যান্ডার্ড সাইন ফাংশন (সিগনাম, এসএনজিএন) রয়েছে?

স্ট্যান্ডার্ড লাইব্রেরিতে নয়, তবে সেখানে copysignযা প্রায় একইভাবে ব্যবহার করা যেতে পারে copysign(1.0, arg)এবং সেখানে একটি সত্য চিহ্ন চিহ্ন রয়েছে boostযা এটি স্ট্যান্ডার্ডের অংশও হতে পারে।

    #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


5
এটি সর্বাধিক ভোট প্রাপ্ত উত্তর হওয়া উচিত, কারণ এটি প্রশ্নে যা বলা হয়েছে তার নিকটতম সম্ভাব্য সমাধান দেয়।
বার্তোসকেপিপি

আমি গত কয়েক মিনিট ধরে ভাবছিলাম যে কেন স্ট্যান্ডার্ড লাইব্রেরিতে সাইন ফাংশন নেই। এটি ঠিক এত সাধারণ - গামা ফাংশনের চেয়ে অবশ্যই বেশি ব্যবহৃত যা cmath শিরোনামে পাওয়া যায়।
তাওজি

4
অনুরূপ প্রশ্নের জন্য প্রায়শই আমি যে ব্যাখ্যাটি পাই তা হ'ল "এটি নিজেকে প্রয়োগ করা যথেষ্ট সহজ" কোন আইএমও কোনও ভাল কারণ নয়। এটি যেখানে মানীকরণ, অদম্য প্রান্তের কেস এবং কোথায় এত ব্যাপকভাবে ব্যবহৃত সরঞ্জাম স্থাপন করা উচিত সে সমস্যাগুলি সম্পূর্ণভাবে বোঝায়।
ক্যাটসকুল

77

স্পষ্টতই, মূল পোস্টারের প্রশ্নের উত্তর নেই no কোনও মানক সি ++ sgnফাংশন নেই।


2
@ এসআর_ আপনি সঠিক নন copysign()দ্বিতীয়টি যদি 0.0 হয় তবে আপনার প্রথম প্যারামিটার 0.0 তৈরি করবে না। অন্য কথায়, জন সঠিক।
অ্যালেক্সিস উইলক

29

উপরের সমাধানগুলির চেয়ে দ্রুততর, সর্বোচ্চ রেটযুক্ত সহ:

(x < 0) ? -1 : (x > 0)

1
এক্স কি ধরণের? নাকি আপনি # ডিফাইন ব্যবহার করছেন?
সম্ভাব্য

3
আপনার ধরণটি দ্রুত নয়। এটি প্রায়শই একটি ক্যাশে মিস করতে পারে।
জেফ্রি ড্রেক

19
মিস করবেন ক্যাশে? আমি নিশ্চিত না কিভাবে। সম্ভবত আপনি শাখার ভুল ব্যাখ্যা?
ক্যাটসকুল

2
আমার কাছে মনে হচ্ছে এটি বিভ্রান্ত পূর্ণ সংখ্যার এবং বুলিয়ান প্রকারের একটি সতর্কবার্তার ফলে আসবে!
সার্জিওল

কিভাবে এই শাখা সঙ্গে দ্রুত হবে?
নিক

29

সি / সি ++ এ কি কোনও স্ট্যান্ডার্ড সাইন ফাংশন (সিগনাম, এসএনজিএন) রয়েছে?

হ্যাঁ, সংজ্ঞা অনুসারে।

সি 99 এবং পরে signbit()ম্যাক্রোটি রয়েছে<math.h>

int signbit(বাস্তব-ভাসমান x); ম্যাক্রো আয় একটি অশূন্য মান যদি এবং কেবল যদি যুক্তি মান চিহ্ন নেতিবাচক। সি 11 §7.12.3.6
signbit


তবুও ওপি কিছু আলাদা চায়।

আমি এমন একটি ফাংশন চাই যা নেতিবাচক সংখ্যার জন্য -1 এবং ইতিবাচক সংখ্যার জন্য +1 প্রদান করে। ... ফ্লোটে কাজ করা একটি ফাংশন

#define signbit_p1_or_n1(x)  ((signbit(x) ?  -1 : 1)

গভীর:

পোস্ট নিম্নবর্ণিত ক্ষেত্রে নির্দিষ্ট নয়: x = 0.0, -0.0, +NaN, -NaN

একটি ক্ল্যাসিক signum()আয় +1উপর x>0, -1উপর x<0এবং 0উপর x==0

অনেক উত্তর ইতিমধ্যে এটি কভার করেছে, কিন্তু ঠিকানা দেয় না x = -0.0, +NaN, -NaN। অনেকগুলি একটি পূর্ণসংখ্যার পয়েন্ট অফ ভিউয়ের জন্য প্রস্তুত থাকে যা সাধারণত নো-অ-নম্বর ( এনএএন ) এবং -0.0 এর অভাব থাকে ।

সাধারণ উত্তরগুলি signnum_typical() অনের মতো ফাংশন করে -0.0, +NaN, -NaN, তারা ফিরে আসে 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;
}

পরিবর্তে, আমি এই কার্যকারিতাটির প্রস্তাব দিই: -0.0, +NaN, -NaNএটি ফিরে আসে -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
আহ, ঠিক আমি পরে যাচ্ছি। এটি স্রেফ ফরো স্মলটাক github.com/pharo-project/pharo/pull/1835 এ পরিবর্তিত হয়েছে এবং আমি ভাবলাম যে নেতিবাচক শূন্য এবং ন্যান আচরণের জন্য হুকুমের আচরণ কিছু আছে (আইইসি 60559 বা আইএসও 10967) ... আমি পছন্দ করি জাভাস্ক্রিপ্ট চিহ্ন developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
aka.nice

16

শাখা ছাড়াই এটি করার একটি উপায় আছে তবে এটি খুব সুন্দর নয়।

sign = -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));

http://graphics.stanford.edu/~seander/bithacks.html

সেই পৃষ্ঠাতে প্রচুর অন্যান্য আকর্ষণীয়, অত্যধিক-চালাক স্টাফও ...


1
আমি যদি লিঙ্কটি সঠিকভাবে পড়ে থাকি তবে কেবল -1 বা 0 ফেরত দেয় আপনি যদি -1, 0, বা +1 চান তবে এটি sign = (v != 0) | -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));বা sign = (v > 0) - (v < 0);
জেড বোসন

1
এর দ্বারা বোঝা যায় যে vপূর্ণসংখ্যার
ধরণটি

12

আপনি যা চান তা যদি সাইনটি পরীক্ষা করা হয় তবে সাইনবিটটি ব্যবহার করুন (এর যুক্তিতে নেতিবাচক চিহ্ন থাকলে সত্যটি প্রত্যাবর্তন করে)। আপনি কেন বিশেষত -1 বা +1 চান তা নিশ্চিত নন; কপিসাইন এটির জন্য আরও সুবিধাজনক তবে এটি মনে হচ্ছে এটি নেতিবাচক শূন্যের জন্য কেবলমাত্র আংশিক সমর্থন সহ কিছু প্ল্যাটফর্মে নেতিবাচক শূন্যের জন্য +1 ফিরে আসবে, যেখানে সাইনবিট সম্ভবত যথার্থ প্রত্যাবর্তন করবে।


7
অনেকগুলি গাণিতিক অ্যাপ্লিকেশন রয়েছে যাতে সাইন (এক্স) প্রয়োজনীয়। অন্যথায় আমি ঠিক করতাম if (x < 0)
চান্স

5

সাধারণভাবে, সি / সি ++ তে কোনও স্ট্যান্ডার্ড সাইনাম ফাংশন নেই এবং এই জাতীয় মৌলিক ক্রিয়াকলাপের অভাব আপনাকে এই ভাষাগুলি সম্পর্কে অনেক কিছু জানায়।

এগুলি ছাড়াও, আমি বিশ্বাস করি যে এই জাতীয় কার্যকারিতা সংজ্ঞায়নের সঠিক পদ্ধতির বিষয়ে উভয় সংখ্যাগরিষ্ঠ দৃষ্টিভঙ্গি কোনও উপায়ে সঠিক এবং এটি সম্পর্কে "বিতর্ক" আসলে একটি অ-যুক্তি হিসাবে একবার আপনি দুটি গুরুত্বপূর্ণ ক্যাভেট বিবেচনায় নিলে:

  • একটি সংকেত ফাংশন সর্বদা এর ক্রিয়াকলাপের অনুরূপ, কোনও abs()ক্রিয়াকলাপের মতো ফিরে আসে, কারণ সাইনাম সাধারণত কোনও পরে প্রক্রিয়া করার পরে একটি নিখুঁত মান দিয়ে গুণনের জন্য ব্যবহৃত হয়। সুতরাং, সাইনামের প্রধান ব্যবহারের ক্ষেত্রে তুলনা করা নয়, পাটিগণিত এবং দ্বিতীয়টি কোনও ব্যয়বহুল পূর্ণসংখ্যার সাথে / থেকে-ভাসমান-পয়েন্ট রূপান্তরকে জড়িত করা উচিত নয়।

  • ভাসমান পয়েন্টের ধরণগুলি একক সঠিক শূন্য মানের বৈশিষ্ট্যযুক্ত না: +0.0 "শূন্যের উপরে অসীম" এবং "০.০" শূন্যের নীচে "হিসাবে ব্যাখ্যা করা যায়। এ কারণেই শূন্যের সাথে জড়িত তুলনাগুলি অভ্যন্তরীণভাবে উভয় মানের তুলনায় অবশ্যই পরীক্ষা করা উচিত এবং এর মতো অভিব্যক্তিটি x == 0.0বিপজ্জনক হতে পারে।

সি সম্পর্কিত, আমি মনে করি যে অবিচ্ছেদ্য প্রকারের সাথে এগিয়ে যাওয়ার সর্বোত্তম উপায়টি হ'ল ভাবটি ব্যবহার করা (x > 0) - (x < 0), কারণ এটি একটি শাখা-মুক্ত ফ্যাশনে অনুবাদ করা উচিত এবং এর জন্য কেবল তিনটি প্রাথমিক ক্রিয়াকলাপ প্রয়োজন। সেরা ইনলাইন ফাংশনগুলি সংজ্ঞায়িত করে যা আর্গুমেন্টের সাথে মিলে যাওয়া রিটার্ন টাইপ প্রয়োগ define _Genericকরে এবং একটি সাধারণ নামের সাথে এই ফাংশনগুলি মানচিত্র করতে একটি সি 11 যুক্ত করে।

ফ্লোটিং পয়েন্ট মান, আমি C11 উপর ভিত্তি করে মনে ইনলাইন ফাংশন copysignf(1.0f, x), copysign(1.0, x)এবং copysignl(1.0l, x)যেতে উপায় হয়, কারণ তারা করছি অত্যন্ত সম্ভবত শাখা-মুক্ত হবে, এবং অতিরিক্ত একটি ফ্লোটিং পয়েন্ট মধ্যে পূর্ণসংখ্যা পিছন থেকে ফলাফলের ভোটদান প্রয়োজন হয় না মান। আপনি সম্ভবত স্পষ্টরূপে মন্তব্য করা উচিত যে আপনার ফ্লোটিং পয়েন্ট বাস্তবায়নের সংকেত শূন্য ফিরবে না কারণ ফ্লোটিং পয়েন্ট শূন্য মান নিজস্ব চালচলন এর, সময় বিবেচ্য বিষয় প্রক্রিয়াকরণের, এবং এছাড়াও এটা প্রায়ই গ্রহণ করতে ফ্লোটিং পয়েন্ট গাণিতিক খুব দরকারী কারণ সঠিক -1 / + + 1 চিহ্ন এমনকি শূন্য মানের জন্যও।


5

সংক্ষেপে আমার সি এর অনুলিপিটি কপিসাইন নামে একটি মানক ফাংশনের অস্তিত্ব প্রকাশ করে যা দরকারী হতে পারে। দেখে মনে হচ্ছে কপিসাইন (১.০, -২.০) -১.০ ফিরে আসবে এবং কপি-সাইন (১.০, ২.০) +1.0 ফিরে আসবে।

খুব কাছের হাহ?


মানক নয়, তবে এটি ব্যাপকভাবে উপলব্ধ হতে পারে। মাইক্রোসফ্ট আন্ডারস্কোর দিয়ে শুরু হয়, এটি হ'ল কনভেনশন যা তারা অ-মানক এক্সটেনশনের জন্য ব্যবহার করে। যদিও আপনি পূর্ণসংখ্যার সাথে কাজ করার সময় সেরা পছন্দ নয়।
মার্ক রান্সম

5
কপিসইগাইন আইএসও সি (সি 99) এবং পসিক্স মান উভয়ই। দেখুন opengroup.org/onlinepubs/000095399/functions/copysign.html
lhf

3
Lhf কি বলেছে। ভিজ্যুয়াল স্টুডিও সি স্ট্যান্ডার্ডের জন্য কোনও রেফারেন্স নয়।
স্টিফেন ক্যানন

3

না, এটি মাতালাবের মতো সি ++ তে বিদ্যমান নেই। আমি এর জন্য আমার প্রোগ্রামগুলিতে ম্যাক্রো ব্যবহার করি।

#define sign(a) ( ( (a) < 0 )  ?  -1   : ( (a) > 0 ) )

5
সি ++ তে ম্যাক্রোগুলির চেয়ে টেমপ্লেটগুলি পছন্দ করা উচিত।
রুস্লান

সি-তে কোনও টেমপ্লেট নেই ...... হ্যালোএকম.com
how-

আমি ভেবেছিলাম এটি একটি ভাল উত্তর তখন আমি নিজের কোডটি দেখলাম এবং এটি পেয়েছি: #define sign(x) (((x) > 0) - ((x) < 0))যা খুব ভাল।
মিশেল রাউজিক

1
একটি ইনলাইন ফাংশন সি এর ম্যাক্রোর চেয়ে ভাল, এবং সি ++ টেমপ্লেটে আরও ভাল
ফুক্লভিভি

3

নীচের ওভারলোড সহ স্বীকৃত উত্তরটি প্রকৃতপক্ষে - টাইপ-সীমাবদ্ধ করে না

template <typename T> inline constexpr
  int signum(T x, std::false_type) {
  return T(0) < x;
}

template <typename T> inline constexpr
  int signum(T x, std::true_type) {
  return (T(0) < x) - (x < T(0));
}

template <typename T> inline constexpr
  int signum(T x) {
  return signum(x, std::is_signed<T>());
}

সি ++ 11 এর জন্য বিকল্প হতে পারে।

template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, int>::type
inline constexpr signum(T const x) {
    return T(0) < x;  
}

template <typename T>
typename std::enable_if<std::is_signed<T>::value, int>::type
inline constexpr signum(T const x) {
    return (T(0) < x) - (x < T(0));  
}

আমার জন্য এটি জিসিসি 5.3.1 তে কোনও সতর্কবার্তা ট্রিগার করে না।


-Wunused-parameterসতর্কতা এড়াতে কেবল নামবিহীন পরামিতি ব্যবহার করুন।
জোনাথন ওয়াকলি

এটা আসলে খুব সত্য। আমি সেটা মিস করেছি. তবে আমি সি ++ 11 বিকল্প আরও যে কোনও উপায়ে পছন্দ করি।
সামভানডুনট

2

বিট অফ টপিক, তবে আমি এটি ব্যবহার করি:

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));
}

এবং আমি প্রথম ফাংশনটি খুঁজে পেয়েছি - "স্ট্যান্ডার্ড" এসএনজিএন () থেকে আরও কার্যকর হওয়ার জন্য দুটি যুক্তিযুক্ত একটি, কারণ এটি প্রায়শই এই জাতীয় কোডে ব্যবহৃত হয়:

int comp(unsigned a, unsigned b){
   return sgn( int(a) - int(b) );
}

বনাম

int comp(unsigned a, unsigned b){
   return sgn(a, b);
}

স্বাক্ষরবিহীন প্রকারের জন্য কোনও castালাই নেই এবং কোনও অতিরিক্ত বিয়োগ নেই।

আসলে আমার কাছে এসজিএন () ব্যবহার করে এই কোডের টুকরো রয়েছে

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);
}

1

প্রশ্নটি পুরান তবে এখন এই ধরণের পছন্দসই ফাংশন রয়েছে। আমি না, বাম শিফট এবং ডেস্ক সহ একটি মোড়ক যুক্ত করেছি।

সঠিক কাঙ্ক্ষিত আচরণ পেতে (নীচের কোডটি আরও দেখুন) আপনি C99 থেকে সাইনবিটের উপর ভিত্তি করে একটি মোড়ক ফাংশন ব্যবহার করতে পারেন ।

X এর চিহ্নটি negativeণাত্মক কিনা তা প্রদান করে।
এটি ইনফিনাইটস, এনএএন এবং জিরোগুলিতেও প্রয়োগ করা যেতে পারে (যদি শূন্য স্বাক্ষরিত না হয় তবে এটি ইতিবাচক হিসাবে বিবেচনা করা হয়

#include <math.h>

int signValue(float a) {
    return ((!signbit(a)) << 1) - 1;
}

এনবি: আমি অপেরাড নট ("!") ব্যবহার করি কারণ সাইনবিটের ফেরতের মান 1 হিসাবে নির্দিষ্ট করা হয়নি (যদিও উদাহরণগুলি আমাদের মনে করে যে এটি সর্বদা এভাবেই থাকবে) তবে নেতিবাচক সংখ্যার জন্য সত্য:

রিটার্ন মান
x- এর চিহ্নটি নেতিবাচক হলে একটি শূন্য-না মান (সত্য); এবং অন্যথায় শূন্য (মিথ্যা)।

তারপরে আমি বাম পাশের শিফ্ট ("<< 1") দিয়ে দুটি দিয়ে গুণ করব যা আমাদের ধনাত্মক সংখ্যার জন্য 2 এবং aণাত্মক একটির জন্য 0 এবং শেষ পর্যন্ত 1 দ্বারা হ্রাস করবে যথাক্রমে ইতিবাচক এবং নেতিবাচক সংখ্যাগুলির জন্য অনুরোধ হিসাবে ওপি।


০ তখনও ইতিবাচক হবে ... যা ওপি যা চেয়েছিল তা হতে পারে বা নাও হতে পারে ...
অ্যান্টি হাপালা

ঠিক আছে আমরা কখনই জানতে পারি না যে ওপি সত্যিকার অর্থে এন = 0 ... কী চেয়েছিল ...!
আন্তোনিন গ্যাভারিল

0

যদিও স্বীকৃত উত্তরের পূর্ণসংখ্যার সমাধানটি বেশ মার্জিত তবে এটি আমাকে বিরক্ত করেছিল যে এটি ডাবল ধরণের জন্য এনএএন ফেরত দিতে সক্ষম হবে না, তাই আমি এটিকে কিছুটা সংশোধন করেছি।

template <typename T> double sgn(T val) {
    return double((T(0) < val) - (val < T(0)))/(val == val);
}

মনে রাখবেন, যে ফ্লোটিং পয়েন্ট NAN ফিরে হিসাবে একটি হার্ড কোডেড বিরোধিতা NANকারণ চিহ্ন কিছুক্ষনের মধ্যে সেট হওয়ার কিছু বাস্তবায়নের , তাই জন্য আউটপুট val = -NANএবং val = NANযাচ্ছি কোন ব্যাপার কি অভিন্ন হবে (যদি আপনি একটি "পছন্দ করা nanএকটি ওভার" আউটপুট -nanআপনি লাগাতে পারেন একটি abs(val)রিটার্ন আগে ...)



0

এখানে একটি শাখা-বান্ধব বাস্তবায়ন:

inline int signum(const double x) {
    if(x == 0) return 0;
    return (1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}

আপনার ডেটাতে অর্ধেক সংখ্যার শূন্য না থাকলে এখানে শাখার ভবিষ্যদ্বাণীকারী একটি শাখাটিকে সবচেয়ে সাধারণ হিসাবে বেছে নেবে। উভয় শাখায় কেবল সাধারণ অপারেশন জড়িত।

বিকল্পভাবে, কিছু সংকলক এবং সিপিইউ আর্কিটেকচারে একটি সম্পূর্ণ শাখাবিহীন সংস্করণ দ্রুততর হতে পারে:

inline int signum(const double x) {
    return (x != 0) * 
        (1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}

এটি আইইইই 754 ডাবল-স্পষ্টতা বাইনারি ফ্লোটিং-পয়েন্ট ফর্ম্যাট: বাইনারি 64 এর জন্য কাজ করে


-1
int sign(float n)
{     
  union { float f; std::uint32_t i; } u { n };
  return 1 - ((u.i >> 31) << 1);
}

এই ফাংশন ধরে:

  • ভাসমান পয়েন্ট সংখ্যাগুলির বাইনারি 32 উপস্থাপনা
  • একটি সংকলক যা নামযুক্ত ইউনিয়ন ব্যবহার করার সময় কঠোর আলিয়াজিং বিধি সম্পর্কে ব্যতিক্রম করে

3
এখানে এখনও কিছু খারাপ অনুমান রয়েছে। উদাহরণস্বরূপ আমি বিশ্বাস করি না যে ভাসমানটির শেষের দিকটি পূর্ণসংখ্যার শেষের গ্যারান্টিযুক্ত। আপনার চেক আইএলপি using৪ ব্যবহার করে যে কোনও আর্কিটেকচারেও ব্যর্থ হয়। সত্যিই, আপনি কেবল পুনর্নির্মাণ করছেন copysign; আপনি যদি ব্যবহার করেন তবে আপনার static_assertসি ++ 11 রয়েছে এবং সম্ভবত এটি ব্যবহার করতে পারে copysign


-3

আপনি যখন এই কাজটি করতে পারেন তখন কেন কেন টের্নারি অপারেটরগুলি ব্যবহার করুন এবং

#define sgn(x) x==0 ? 0 : x/abs(x)

3
আপনার সংজ্ঞা এছাড়াও একটি ternary অপারেটর ব্যবহার করে।
মার্টিন আর

হ্যাঁ অবশ্যই, তবে এটি শূন্য এবং অ-শূন্য সংখ্যা পৃথক করতে কেবল একটি তিনটি অপারেটর ব্যবহার করে। অন্যের সংস্করণগুলিতে ইতিবাচক, নেতিবাচক এবং শূন্য পৃথক করতে নেস্টেড টের্নারি অপগুলি অন্তর্ভুক্ত।
জাগ্রীত

একটি পূর্ণসংখ্যা বিভাগ ব্যবহার করা খুব অকার্যকর এবং অ্যাবস () কেবলমাত্র পূর্ণসংখ্যার জন্য।
মিশেল রাউজিক

অপরিবর্তিত আচরণ সম্ভব যখন x == INT_MIN
chux -
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.